J'essaie actuellement d'implémenter un système d'entités basé sur des composants, où une entité est essentiellement juste un ID et quelques méthodes d'assistance liant un tas de composants ensemble pour former un objet de jeu. Certains objectifs comprennent:
- Les composants ne contiennent que l'état (par exemple position, santé, nombre de munitions) => la logique entre dans les "systèmes", qui traitent ces composants et leur état (par exemple PhysicsSystem, RenderSystem, etc.)
- Je veux implémenter des composants et des systèmes à la fois en C # pur et par script (Lua). Fondamentalement, je veux pouvoir définir des composants et des systèmes complètement nouveaux directement dans Lua sans avoir à recompiler ma source C #.
Maintenant, je cherche des idées sur la façon de gérer cela de manière efficace et cohérente, donc je n'ai pas besoin d'utiliser une syntaxe différente pour accéder aux composants C # ou aux composants Lua, par exemple.
Mon approche actuelle serait d'implémenter des composants C # en utilisant des propriétés publiques régulières, probablement décorées avec certains attributs informant l'éditeur des valeurs par défaut et d'autres choses. Ensuite, j'aurais une classe C # "ScriptComponent", qui enveloppe simplement une table Lua en interne, cette table étant créée par un script et contenant tout l'état de ce type de composant particulier. Je ne veux pas vraiment accéder à cet état beaucoup du côté C #, car je ne saurais pas au moment de la compilation, quels ScriptComponents avec quelles propriétés seraient disponibles pour moi. Néanmoins, l'éditeur devra y accéder, mais une interface simple comme celle-ci devrait suffire:
public ScriptComponent : IComponent
{
public T GetProperty<T>(string propertyName) {..}
public void SetProperty<T>(string propertyName, T value) {..}
}
Cela accéderait simplement à la table Lua et définirait et récupérerait ces propriétés à partir de Lua et cela pourrait facilement être également inclus dans les composants C # purs (mais utilisez ensuite les propriétés C # normales, par réflexion ou quelque chose). Cela ne serait utilisé que dans l'éditeur, pas par le code de jeu normal, donc les performances ne sont pas aussi importantes ici. Cela nécessiterait de générer ou d'écrire à la main des descriptions de composants documentant les propriétés d'un certain type de composant, mais ce ne serait pas un problème énorme et pourrait être suffisamment automatisé.
Cependant, comment accéder aux composants du côté Lua? Si j'appelle quelque chose comme getComponentsFromEntity(ENTITY_ID)
je vais probablement obtenir un tas de composants natifs C #, y compris "ScriptComponent", en tant que données utilisateur. Accéder aux valeurs de la table Lua encapsulée me ferait appeler la GetProperty<T>(..)
méthode au lieu d'accéder directement aux propriétés, comme avec les autres composants C #.
Peut-être écrire une getComponentsFromEntity()
méthode spéciale uniquement pour être appelée à partir de Lua, qui renvoie tous les composants natifs C # en tant que données utilisateur, à l'exception de "ScriptComponent", où il renverra la table encapsulée à la place. Mais il y aura d'autres méthodes liées aux composants et je ne veux pas vraiment dupliquer toutes ces méthodes pour être appelées à partir du code C # ou du script Lua.
Le but ultime serait de gérer tous les types de composants de la même manière, sans syntaxe de cas particulier faisant la différence entre les composants natifs et les composants Lua - en particulier du côté Lua. Par exemple, j'aimerais pouvoir écrire un script Lua comme ça:
entity = getEntity(1);
nativeComponent = getComponent(entity, "SomeNativeComponent")
scriptComponent = getComponent(entity, "SomeScriptComponent")
nativeComponent.NativeProperty = 5
scriptComponent.ScriptedProperty = 3
Le script ne devrait pas se soucier du type de composant qu'il a réellement obtenu et j'aimerais utiliser les mêmes méthodes que j'utiliserais du côté C # pour récupérer, ajouter ou supprimer des composants.
Peut-être y a-t-il des exemples d'implémentations d'intégration de scripts avec des systèmes d'entités comme ça?
Réponses:
Un corollaire de la réponse de FXIII est que vous devez concevoir tout (ce serait moddable) dans le langage de script premier (ou au moins une partie très décent de celui - ci) pour vous assurer que votre logique d'intégration des dispositions réellement pour modding. Lorsque vous êtes certain que votre intégration de script est suffisamment polyvalente, réécrivez les bits requis en C #.
Personnellement, je déteste la
dynamic
fonctionnalité en C # 4.0 (je suis un drogué de langage statique) - mais c'est sans aucun doute un scénario où il devrait être utilisé et où il brille vraiment. Vos composants C # seraient simplement des objets comportementaux forts / expando .Vos composants Lua seraient complètement dynamiques (le même article ci-dessus devrait vous donner une idée de la façon de l'implémenter). Par exemple:
Maintenant, parce que vous utilisez,
dynamic
vous pouvez utiliser des objets Lua comme s'ils étaient de vraies classes en C #.la source
Je préfère faire le contraire: écrire tout en utilisant un langage dynamique, puis traquer les embouteillages (le cas échéant). Une fois que vous en avez trouvé, vous pouvez réimplémenter sélectivement les fonctionnalités impliquées en utilisant un C # ou (plutôt) C / C ++.
Je vous le dis principalement parce que ce que vous essayez de faire est de confiner les flexibilités de votre système dans la partie C #; à mesure que le système devient complexe, votre "moteur" C # commencera à ressembler à un interpréteur dynamique, probablement pas le meilleur. La question est: êtes-vous prêt à investir le plus de temps possible dans l'écriture d'un moteur C # générique ou à étendre votre jeu?
Si votre cible est la seconde, comme je le crois, vous utiliserez probablement votre temps au mieux en vous concentrant sur vos mécanismes de jeu, en laissant un interprète chevronné exécuter le code dynamique.
la source