Attualmente sto cercando di implementare un sistema di entità basato su componenti, in cui un'entità è fondamentalmente solo un ID e alcuni metodi di supporto che uniscono un gruppo di componenti per formare un oggetto di gioco. Alcuni obiettivi includono:
- I componenti contengono solo stato (ad es. Posizione, salute, numero di munizioni) => la logica va in "sistemi", che elaborano questi componenti e il loro stato (ad es. PhysicsSystem, RenderSystem, ecc.)
- Voglio implementare componenti e sistemi sia in puro C # che tramite scripting (Lua). Fondamentalmente voglio essere in grado di definire componenti e sistemi completamente nuovi direttamente in Lua senza dover ricompilare il mio sorgente C #.
Ora sto cercando idee su come gestirlo in modo efficiente e coerente, quindi non ho bisogno di usare una sintassi diversa per accedere ai componenti C # o ai componenti Lua, ad esempio.
Il mio approccio attuale sarebbe quello di implementare componenti C # usando proprietà pubbliche regolari, probabilmente decorate con alcuni attributi che dicevano all'editore di valori e cose predefiniti. Quindi avrei una classe C # "ScriptComponent", che avvolge semplicemente una tabella Lua internamente con questa tabella creata da uno script e contenente tutto lo stato di quel particolare tipo di componente. Non voglio davvero accedere a quello stato dal lato C #, come non saprei al momento della compilazione, quali ScriptComponents con quali proprietà sarebbero disponibili per me. Tuttavia, l'editor dovrà accedervi, ma una semplice interfaccia come la seguente dovrebbe essere sufficiente:
public ScriptComponent : IComponent
{
public T GetProperty<T>(string propertyName) {..}
public void SetProperty<T>(string propertyName, T value) {..}
}
Questo semplicemente accede alla tabella Lua e imposta e recupera quelle proprietà da Lua e potrebbe essere facilmente incluso anche nei componenti C # puri (ma usa le normali proprietà C #, attraverso la riflessione o qualcosa del genere). Questo sarebbe usato solo nell'editor, non dal normale codice di gioco, quindi le prestazioni non sono così importanti qui. Sarebbe necessario generare o scrivere a mano alcune descrizioni dei componenti documentando quali proprietà offre effettivamente un determinato tipo di componente, ma questo non sarebbe un grosso problema e potrebbe essere sufficientemente automatizzato.
Tuttavia, come accedere ai componenti dal lato Lua? Se faccio una chiamata a qualcosa del genere getComponentsFromEntity(ENTITY_ID)
probabilmente riceverò solo un mucchio di componenti C # nativi, incluso "ScriptComponent", come userdata. L'accesso ai valori dalla tabella Lua racchiusa mi farebbe chiamare il GetProperty<T>(..)
metodo invece di accedere direttamente alle proprietà, come con gli altri componenti C #.
Forse scrivere un getComponentsFromEntity()
metodo speciale solo per essere chiamato da Lua, che restituisce tutti i componenti nativi di C # come userdata, ad eccezione di "ScriptComponent", dove restituirà invece la tabella spostata. Ma ci saranno altri metodi relativi ai componenti e non voglio davvero duplicare tutti questi metodi sia per essere chiamati dal codice C # sia dallo script Lua.
L'obiettivo finale sarebbe quello di gestire tutti i tipi di componenti allo stesso modo, senza che la sintassi del caso speciale distingua tra componenti nativi e componenti Lua, specialmente dal lato Lua. Ad esempio, vorrei poter scrivere una sceneggiatura di Lua in questo modo:
entity = getEntity(1);
nativeComponent = getComponent(entity, "SomeNativeComponent")
scriptComponent = getComponent(entity, "SomeScriptComponent")
nativeComponent.NativeProperty = 5
scriptComponent.ScriptedProperty = 3
Lo script non dovrebbe interessarsi del tipo di componente effettivamente ottenuto e mi piacerebbe usare gli stessi metodi che userei dal lato C # per recuperare, aggiungere o rimuovere componenti.
Forse ci sono alcune implementazioni di esempio di integrazione di script con sistemi di entità del genere?