Все знают, что в игровом движке нужно каким-то образом хранить данные об игровых объектах.
И за множество лет обуздания геймдева появилось немало архитектур:
Многоуровневая. Разделяет задачи, возможность менять одни слои на другие
Event-driven. Исходя из названия, - главные в движке - события
Parallel Task. Каждая система в своём мире и почти не контактирует с другими
Component-based. Делит игру на reusable компоненты
ECS. О нём мы и поговорим
Я, в своём движке Factory Engine, решил использовать архитектуру ECS (также Unity использовал такую систему в DOTS). "Но что же это значит?" - спросите вы меня, а я отвечу: ECS расшифровывается как Entity-Component-System.
Исходя из расшифровки вы можете сделать вывод, что эта архитектура держится на 3 столбах, и будете чертовски правы! ECS - это Data-driven подход к созданию движка, а его данные и логика разнесены в разные места.
Почему важно выбрать правильную архитектуру движка? Ну вот смотрите, Unity изнутри:

Это диаграмма классов движка, представляете, как трудно что-либо добавлять в движок?
А вот многоуровневая система движка Unreal Engine:

Уже намного лучше.
Но ECS - это Data-driven архитектура. И что это вообще значит? А значит это, что поведение движка определяется данными и не захардкожена в движке.
Первый столб. Entities
Первое, с чем мы сталкиваемся в расшифровке - Entity. Что это значит? Какие сущности? Сущности - это наши игровые объекты, с которыми мы можем взаимодействовать.
Они не имеют ни логики, ни данных сами по себе. Их назначение - хранить в себе указатели на компоненты для того, чтобы системы могли с ними взаимодействовать. Например:
...
class GameObject : Entity {
Component[] components = {
Transform2D, Velocity2D
};
};
...
Теперь мы плавно переходим ко второму столбу.
Второй столб. Components
Второе - это Components. Из предыдущей главы мы поняли, что Entity хранят указатели на Component, но зачем?
Как я уже сказал: Entity не хранят данные. Данные хранятся внутри компонентов. Например:
...
class Transform2D : Component {
Vec2 position;
Vec2 scale;
float rotation;
};
class Velocity2D : Component {
Vec2 velocity;
};
...
Компоненты так же не имеют логики, её реализует следующий и последний столб.
Третий столб. Systems
Последнее, о чём мы поговорим - Systems. Это системы (как ни странно). Они выполняют всю логику над компонентами и сущностями. Именно они отвечают за то, "что" и "как" делать в игре.
Системы могут получить доступ к любой сущности и любому компоненту. Например:
...
class Movement : System {
void DoStuff() {
Entity[] entities = Engine.Entities.With<Transform2D>().With<Velocity2D>();
foreach (entity in entities) {
entity.transform.position += entity.velocity;
}
}
};
...
Это был простенький пример системы, которая каждый вызов двигает каждый объект на его скорость.
Заключение
Всё, это конец этого поста. Изображения и немного информации я взял из этой статьи на хабре.
















0 comments