В настоящее время я пытаюсь реализовать систему сущностей, основанную на компонентах, где сущность - это в основном просто ID и несколько вспомогательных методов, связывающих кучу компонентов вместе для формирования игрового объекта. Некоторые цели этого включают:
- Компоненты содержат только состояние (например, положение, состояние, количество боеприпасов) => логика переходит в «системы», которые обрабатывают эти компоненты и их состояние (например, PhysicsSystem, RenderSystem и т. Д.)
- Я хочу реализовать компоненты и системы как на чистом C #, так и с помощью сценариев (Lua). По сути, я хочу иметь возможность определять совершенно новые компоненты и системы непосредственно в Lua без необходимости перекомпиляции моего источника C #.
Сейчас я ищу идеи о том, как эффективно и последовательно справляться с этим, поэтому мне не нужно использовать другой синтаксис для доступа, например, к компонентам C # или Lua.
Мой текущий подход заключается в реализации компонентов C # с использованием обычных, открытых свойств, вероятно, украшенных некоторыми атрибутами, сообщающими редактору о значениях по умолчанию и прочем. Тогда у меня был бы класс C # «ScriptComponent», который просто оборачивает таблицу Lua внутри, при этом эта таблица создается скриптом и содержит все состояния этого конкретного типа компонента. Я не очень хочу получать доступ к этому состоянию со стороны C #, так как я не знаю во время компиляции, какие ScriptComponents с какими свойствами будут доступны для меня. Тем не менее, редактору потребуется доступ к этому, но достаточно простого интерфейса, подобного следующему:
public ScriptComponent : IComponent
{
public T GetProperty<T>(string propertyName) {..}
public void SetProperty<T>(string propertyName, T value) {..}
}
Это просто получит доступ к таблице Lua, установит и получит эти свойства из Lua, и его также можно будет легко включить в чистые компоненты C # (но затем использовать обычные свойства C # через отражение или что-то в этом роде). Это будет использоваться только в редакторе, а не в обычном игровом коде, поэтому производительность здесь не так важна. Было бы необходимо сгенерировать или написать вручную некоторые описания компонентов, документирующие, какие свойства на самом деле предлагает определенный тип компонентов, но это не было бы большой проблемой и могло бы быть достаточно автоматизировано.
Однако как получить доступ к компонентам со стороны Lua? Если я сделаю вызов чего-то подобного, getComponentsFromEntity(ENTITY_ID)
я, вероятно, просто получу набор нативных компонентов C #, в том числе ScriptComponent, в качестве пользовательских данных. Доступ к значениям из свернутой таблицы Lua приведет к тому, что я вызову GetProperty<T>(..)
метод вместо прямого доступа к свойствам, как с другими компонентами C #.
Может быть, написать специальный getComponentsFromEntity()
метод, который будет вызываться только из Lua, который возвращает все нативные компоненты C # в качестве пользовательских данных, кроме «ScriptComponent», где вместо этого он будет возвращать упакованную таблицу. Но будут другие методы, связанные с компонентами, и я не хочу дублировать все эти методы как для вызова из кода C #, так и из сценария Lua.
Конечная цель состоит в том, чтобы обрабатывать все типы компонентов одинаково, без особого синтаксиса различий между нативными компонентами и компонентами Lua - особенно со стороны Lua. Например, я бы хотел написать сценарий Lua следующим образом:
entity = getEntity(1);
nativeComponent = getComponent(entity, "SomeNativeComponent")
scriptComponent = getComponent(entity, "SomeScriptComponent")
nativeComponent.NativeProperty = 5
scriptComponent.ScriptedProperty = 3
Скрипт не должен заботиться о том, какой компонент он на самом деле получил, и я хотел бы использовать те же методы, которые я использовал бы на стороне C #, для извлечения, добавления или удаления компонентов.
Может быть, есть примеры реализации интеграции сценариев с такими системами сущностей?