Ich versuche derzeit, ein komponentenbasiertes Entitätssystem zu implementieren, bei dem eine Entität im Grunde nur eine ID und einige Hilfsmethoden sind, die eine Reihe von Komponenten zu einem Spielobjekt zusammenbinden. Einige Ziele davon sind:
- Komponenten enthalten nur Status (z. B. Position, Gesundheit, Munitionszahl) => Logik geht in "Systeme", die diese Komponenten und ihren Status verarbeiten (z. B. PhysicsSystem, RenderSystem usw.).
- Ich möchte Komponenten und Systeme sowohl in reinem C # als auch durch Scripting (Lua) implementieren. Grundsätzlich möchte ich in der Lage sein, völlig neue Komponenten und Systeme direkt in Lua zu definieren, ohne meine C # -Quelle neu kompilieren zu müssen.
Jetzt suche ich nach Ideen, wie ich effizient und konsistent damit umgehen kann, damit ich beispielsweise keine andere Syntax verwenden muss, um auf C # -Komponenten oder Lua-Komponenten zuzugreifen.
Mein aktueller Ansatz wäre die Implementierung von C # -Komponenten mithilfe regulärer öffentlicher Eigenschaften, die wahrscheinlich mit einigen Attributen versehen sind, die dem Editor Informationen zu Standardwerten und anderen Elementen geben. Dann hätte ich eine C # -Klasse "ScriptComponent", die nur eine Lua-Tabelle intern umschließt, wobei diese Tabelle von einem Skript erstellt wird und den gesamten Status dieses bestimmten Komponententyps enthält. Ich möchte von der C # -Seite nicht wirklich auf diesen Status zugreifen, da ich zum Zeitpunkt der Kompilierung nicht wissen würde, welche ScriptComponents mit welchen Eigenschaften mir zur Verfügung stehen würden. Der Editor muss zwar darauf zugreifen, aber eine einfache Oberfläche wie die folgende sollte ausreichen:
public ScriptComponent : IComponent
{
public T GetProperty<T>(string propertyName) {..}
public void SetProperty<T>(string propertyName, T value) {..}
}
Dies würde einfach auf die Lua-Tabelle zugreifen und diese Eigenschaften von Lua festlegen und abrufen, und es könnte leicht auch in den reinen C # -Komponenten enthalten sein (aber dann die regulären C # -Eigenschaften durch Reflexion oder so etwas verwenden). Dies wird nur im Editor verwendet, nicht im regulären Spielcode, daher ist die Leistung hier nicht so wichtig. Es würde es notwendig machen, einige Komponentenbeschreibungen zu generieren oder handschriftlich zu schreiben, die dokumentieren, welche Eigenschaften ein bestimmter Komponententyp tatsächlich bietet, aber das wäre kein großes Problem und könnte ausreichend automatisiert werden.
Wie kann man jedoch von der Lua-Seite auf Komponenten zugreifen? Wenn ich so etwas getComponentsFromEntity(ENTITY_ID)
anrufe, bekomme ich wahrscheinlich nur ein paar native C # -Komponenten, einschließlich "ScriptComponent", als Benutzerdaten. Der Zugriff auf die Werte aus der umschlossenen Lua-Tabelle würde dazu führen, dass ich die GetProperty<T>(..)
Methode aufrufe, anstatt wie bei den anderen C # -Komponenten direkt auf die Eigenschaften zuzugreifen.
Schreiben Sie möglicherweise eine spezielle getComponentsFromEntity()
Methode, die nur von Lua aufgerufen werden soll. Sie gibt alle nativen C # -Komponenten als Benutzerdaten zurück, mit Ausnahme von "ScriptComponent", wo stattdessen die umschlossene Tabelle zurückgegeben wird. Es wird aber auch andere komponentenbezogene Methoden geben, und ich möchte nicht alle diese Methoden duplizieren, um sie sowohl aus dem C # -Code als auch aus dem Lua-Skript aufzurufen.
Das ultimative Ziel wäre es, alle Arten von Komponenten gleich zu behandeln, ohne dass eine spezielle Fallsyntax zwischen nativen Komponenten und Lua-Komponenten unterscheidet - insbesondere von der Lua-Seite. Zum Beispiel möchte ich in der Lage sein, ein solches Lua-Skript zu schreiben:
entity = getEntity(1);
nativeComponent = getComponent(entity, "SomeNativeComponent")
scriptComponent = getComponent(entity, "SomeScriptComponent")
nativeComponent.NativeProperty = 5
scriptComponent.ScriptedProperty = 3
Das Skript sollte sich nicht darum kümmern, welche Art von Komponente es tatsächlich hat, und ich möchte dieselben Methoden verwenden, die ich von der C # -Seite zum Abrufen, Hinzufügen oder Entfernen von Komponenten verwenden würde.
Vielleicht gibt es einige Beispielimplementierungen für die Integration von Skripten in solche Entitätssysteme?