🚀 Benchmarks 🚀
⚙️ Unity module ⚙️
❗️ Гайд миграции с версии 1.0.x на 1.2.x ❗️
Static ECS - C# Binary Entity component system framework
- Легковесность
- Производительность
- Отсутствие аллокаций
- Без Unsafe
- Основан на статике и структурах
- Типобезопасность
- Бесплатные абстракции
- Мощный механизм запросов
- Минимум болерплейта
- Совместимость с Unity с поддержкой Il2Cpp и Burst
- Совместимость с другими C# движками
- Совместимость с Native AOT
Оглавление
- Контакты
- Установка
- Концепция
- Быстрый старт
- Возможности
- Производительность
- Unity интеграция
- Вопрос-ответ
- Лицензия
Контакты
Установка
Библиотека имеет зависимость на StaticPack версии 1.0.6 для бинарной сериализации, StaticPack должен быть так же установлен
-
В виде исходников
Со страницы релизов или как архив из нужной ветки. В ветке
masterстабильная проверенная версия -
Установка для Unity
- Как git модуль в Unity PackageManager
https://github.com/Felid-Force-Studios/StaticEcs.git
https://github.com/Felid-Force-Studios/StaticPack.git - Или добавление в манифест
Packages/manifest.json
"com.felid-force-studios.static-ecs": "https://github.com/Felid-Force-Studios/StaticEcs.git"
"com.felid-force-studios.static-pack": "https://github.com/Felid-Force-Studios/StaticPack.git"
- Как git модуль в Unity PackageManager
Концепция
StaticEcs — новая архитектура ECS, основанная на инвертированной иерархической bitmap модели. В отличие от традиционных фреймворков ECS, которые полагаются на архетипы или разреженные наборы, в этой конструкции используется инвертированная индексная структура, в которой каждый тип компонента владеет масками активных сущностей, а не сущности хранят маски компонентов. Иерархическая агрегация этих масок обеспечивает логарифмическое индексирование блоков сущностей, что позволяет осуществлять фильтрацию блоков O(1) и эффективную параллельную итерацию с помощью битовых операций. Этот подход полностью устраняет миграцию архетипов и sparse set индирекцию, предлагая прямой доступ к памяти в стиле SoA с минимальным количеством промахов кэша. Модель обеспечивает до 64 раз меньшее количество запросов к памяти на блок и линейно масштабируется с количеством активных наборов компонентов, что делает ее идеальной для крупномасштабных симуляций, реактивного ИИ и открытых миров.
- Основная идея данной реализации в статике, все данные о мире и компонентах находятся в статических классах, что дает возможность избегать дорогостоящих виртуальных вызовов, иметь удобный API со множеством сахара
- Данный фреймворк нацелен на максимальную простоту использования, скорость и комфорт написания кода без жертв в производительности
- Доступно создание мульти-миров, строгая типизация, обширные бесплатные абстракции
- Система сериализации
- Система отношений сущностей
- Многопоточная обработка
- Низкое потребление памяти
- Основан на Bitmap архитектуре, нет архетипов, нет sparse-set
- Фреймворк создан для нужд частного проекта и выложен в open-source.
Быстрый старт
using FFS.Libraries.StaticEcs;
// Определяем тип мира
public struct WT : IWorldType { }
// Определяем типы-алиасы для удобного доступа к типам библиотеки
public abstract class W : World<WT> { }
// Определяем тип систем
public struct SystemsType : ISystemsType { }
// Определяем тип-алиас для удобного доступа к системам
public abstract class Systems : W.Systems<SystemsType> { }
// Определяем компоненты
public struct Position : IComponent { public Vector3 Value; }
public struct Direction : IComponent { public Vector3 Value; }
public struct Velocity : IComponent { public float Value; }
// Определяем системы
public readonly struct VelocitySystem : IUpdateSystem {
public void Update() {
foreach (var entity in W.Query.Entities<All<Position, Velocity, Direction>>()) {
entity.Ref<Position>().Value += entity.Ref<Direction>().Value * entity.Ref<Velocity>().Value;
}
// Или
W.Query.For((ref Position pos, ref Velocity vel, ref Direction dir) => {
pos.Value += dir.Value * vel.Value;
});
}
}
public class Program {
public static void Main() {
// Создаем данные мира
W.Create(WorldConfig.Default());
// Регистрируем компоненты
W.RegisterComponentType<Position>();
W.RegisterComponentType<Direction>();
W.RegisterComponentType<Velocity>();
// Инициализируем мир
W.Initialize();
// Создаем системы
Systems.Create();
Systems.AddUpdate(new VelocitySystem());
// Инициализируем системы
Systems.Initialize();
// Создание сущности
var entity = W.Entity.New(
new Velocity { Value = 1f },
new Position { Value = Vector3.Zero },
new Direction { Value = Vector3.UnitX }
);
// Обновление всех систем - вызывается в каждом кадре
Systems.Update();
// Уничтожение систем
Systems.Destroy();
// Уничтожение мира и очистка всех данных
W.Destroy();
}
}