Наразі я намагаюся реалізувати компонентну систему сутностей, де суть є лише ідентифікатором та деякими допоміжними методами, пов’язуючи купу компонентів разом для формування об’єкта гри. Деякі цілі:
- Компоненти містять лише стан (наприклад, положення, стан здоров'я, кількість патронів) => логіка переходить у "системи", які обробляють ці компоненти та їх стан (наприклад, 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:
entity = getEntity(1);
nativeComponent = getComponent(entity, "SomeNativeComponent")
scriptComponent = getComponent(entity, "SomeScriptComponent")
nativeComponent.NativeProperty = 5
scriptComponent.ScriptedProperty = 3
Сценарій не має байдуже, який саме компонент він отримав насправді, і я хотів би використовувати ті самі методи, які б я використовував зі сторони C # для отримання, додавання або видалення компонентів.
Можливо, є кілька прикладних реалізацій інтеграції сценаріїв із подібними системами?