Скриптовая интеграция IgdrasilECS

IgdrasilECS предоставляет чистые ECS-модули для скриптов без привязки к сценам. Все операции со сценой (добавление сущностей в активную сцену, загрузка/выгрузка сцен, управление системами сцены) вынесены в модули IgdrasilSceneSystem.

Модули

IgdrasilEngine.Engine.Scripting.Modules.ECS
- ECSModule                  // сущности и компоненты (scene-agnostic)
- ECSComponentFactoryModule  // динамическое создание и рефлексию компонентов
- ECSEventsModule            // события сущности и компонентов
- ECSModuleBundle            // регистрация всех ECS-модулей
// ECSSystemModule — deprecated, не подключается

Быстрый старт

using IgdrasilEngine.Engine.Scripting.Lua;
using IgdrasilEngine.Engine.Scripting.Modules.ECS;
using IgdrasilEngine.Engine.Scripting.Modules.SceneManagement;

// Движок скриптинга
var engine = new LuaEngine();

// Регистрируем ECS-модули (scene-agnostic)
ECSModuleBundle.RegisterModules<LuaModuleInterface>(
    engine,
    typeof(MyComponent).Assembly // сборки с вашими компонентами
);

// (Опционально) регистрируем сценовые модули для работы с текущей сценой
SceneModuleBundle.RegisterModules<LuaModuleInterface>(engine);

ECS Module (ecs)

Чистые операции над сущностями и компонентами. Модуль не хранит коллекцию сущностей: вы создаёте их и сами решаете, где хранить (обычно — добавить в активную сцену через scene.addEntityToScene).

Сущности

local ecs = require("ecs")

local player = ecs.createEntity("Player")
player.IsActive = true
-- потом добавьте в сцену: scene.addEntityToScene(player)

Компоненты

-- добавление / удаление
ecs.addComponent(player, health)
ecs.removeComponent(player, health)

-- получение/проверка по типу
local health = ecs.getComponent(player, HealthComponentType)
local has = ecs.hasComponent(player, HealthComponentType)
local many = ecs.getComponents(player, HealthComponentType)
local all = ecs.getAllComponents(player)

-- работа с тегами
ecs.addComponentWithTag(player, "health", health)
local tagged = ecs.getComponentByTag(player, "health")
ecs.removeComponentByTag(player, "health")
local tags = ecs.getComponentTags(player)

Factory Module (ecs.factory)

Динамическое создание компонентов через рефлексию.

local factory = require("ecs.factory")

local health = factory.createComponent("HealthComponent")
local transform = factory.createComponentWithParams("TransformComponent", {0, 0})

-- поля
local fields = factory.getComponentFields(health)
factory.setComponentField(health, "currentHealth", 100)
local hp = factory.getComponentField(health, "currentHealth")

-- свойства
local props = factory.getComponentProperties(health)
factory.setComponentProperty(health, "MaxHealth", 150)
local max = factory.getComponentProperty(health, "MaxHealth")

-- типы
local names = factory.getAllComponentTypeNames()

Events Module (ecs.events)

События на уровне сущности и компонентов.

local events = require("ecs.events")

-- сущность: добавление/удаление компонентов
local cbAdd = events.onComponentAdded(player, function(comp) print("added") end)
local cbRem = events.onComponentRemoved(player, function(comp) print("removed") end)
events.offComponentAdded(player, cbAdd)
events.offComponentRemoved(player, cbRem)

-- компонент: произвольные изменения
local sub = events.subscribeComponentChange(health, function(comp) print("changed") end)
events.invokeComponentChange(health)
events.unsubscribeComponentChange(health, sub)

Взаимодействие со сценой

ECS-модули не знают о сценах. Чтобы работать с активной сценой (добавлять сущности, получать списки сущностей и систем, загружать/выгружать сцены), используйте модули из IgdrasilSceneSystem:

Пример добавления сущности в сцену:

local ecs = require("ecs")
local scene = require("scene")

local e = ecs.createEntity("Player")
scene.addEntityToScene(e) -- теперь сущность участвует в сцене

Советы по производительности

  1. Кешируйте ссылки на компоненты вместо повторных поисков.
  2. Используйте теги для быстрого доступа к часто используемым компонентам.
  3. Минимизируйте число подписок — подписывайтесь только там, где нужна реакция.
  4. При массовых операциях группируйте изменения (батчинг) перед вызовом событий.