From 5b9e23f85290fa4f1d4177082f13047b4923b4b1 Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Wed, 18 Mar 2026 13:25:34 +0800 Subject: [PATCH] update readme --- README-RU.md | 78 +++++++++++++------------- README-ZH.md | 147 +++++++++++++++++++++++++++++-------------------- README.md | 151 +++++++++++++++++++++++++++++++-------------------- 3 files changed, 219 insertions(+), 157 deletions(-) diff --git a/README-RU.md b/README-RU.md index 930d102..ce2d01c 100644 --- a/README-RU.md +++ b/README-RU.md @@ -20,28 +20,26 @@ -
+
Русский
-
+
English
-
+
中文
-
- -DragonECS - это [ECS](https://en.wikipedia.org/wiki/Entity_component_system) фреймворк нацеленный на максимальную удобность, модульность, расширяемость и производительность динамического изменения сущностей. Разработан на чистом C#, без зависимостей и генерации кода. Вдохновлен [LeoEcs Lite](https://github.com/Leopotam/ecslite). +DragonECS - это [ECS](https://en.wikipedia.org/wiki/Entity_component_system) фреймворк, нацеленный на максимальную удобность, модульность, расширяемость и производительность динамического изменения сущностей. Разработан на чистом C#, без зависимостей и генерации кода. Вдохновлен [LeoEcs Lite](https://github.com/Leopotam/ecslite). > [!WARNING] > Проект предрелизной версии, поэтому API может меняться. В ветке main актуальная и рабочая версия. @@ -81,20 +79,20 @@ DragonECS - это [ECS](https://en.wikipedia.org/wiki/Entity_component_system) - [FAQ](#faq) - [Обратная связь](#обратная-связь) -
+ # Установка Семантика версионирования - [Открыть](https://gist.github.com/DCFApixels/e53281d4628b19fe5278f3e77a7da9e8#file-dcfapixels_versioning_ru-md) ## Окружение Обязательные требования: -+ Минимальная версия C# 7.3; ++ Минимальная версия C#: 7.3. Поддерживает: + NativeAOT; + Игровые движки с C#: Unity, Godot, MonoGame и т.д. -Протестировано: -+ **Unity:** Минимальная версия 2021.2.0; +Протестировано на: +* **Unity:** Минимальная версия 2021.2.0. ## Установка для Unity > Рекомендуется так же установить расширение [Интеграция с движком Unity](https://github.com/DCFApixels/DragonECS-Unity) @@ -110,8 +108,8 @@ https://github.com/DCFApixels/DragonECS.git * ### В виде исходников Можно так же напрямую скопировать в проект исходники фреймворка. + -
# Расширения * Интеграции: @@ -131,14 +129,14 @@ https://github.com/DCFApixels/DragonECS.git * [Шаблоны кода IDE](https://gist.github.com/ctzcs/0ba948b0e53aa41fe1c87796a401660b) и [для Unity](https://gist.github.com/ctzcs/d4c7730cf6cd984fe6f9e0e3f108a0f1) > *Твое расширение? Если разрабатываешь расширение для DragonECS, пиши [сюда](#обратная-связь). -
+ # Основные концепции ## Entity -**Сущности** - это то к чему крепятся данные. Для доступа к сущности используются идентификаторы двух типов: +**Сущности** - это то, к чему крепятся данные. Для доступа к сущности используются идентификаторы двух типов: * `int` - однократный идентификатор, применяется в пределах одного тика. Не рекомендуется использовать для хранения; * `entlong` - долговременный идентификатор, содержит метку поколения, что делает его уникальным навсегда. Подходит для хранения. -``` c# +```c# // Создание новой сущности в мире. int entityID = _world.NewEntity(); @@ -156,7 +154,7 @@ int newEntityID = _world.CloneEntity(entityID); Работа с entlong -``` c# +```c# // Конвертация int в entlong. entlong entity = _world.GetEntityLong(entityID); // упрощенная версия @@ -216,7 +214,7 @@ class SomeSystem : IEcsPreInit, IEcsInit, IEcsRun, IEcsDestroy Пример системы -``` c# +```c# // Система class DamageSystem : IEcsRun, IEcsInject { @@ -254,7 +252,7 @@ public struct Health : IEcsComponent -
+ # Концепции фреймворка ## Пайплайн @@ -285,9 +283,9 @@ class SomeSystem : IEcsRun, IEcsPipelineMember ``` > Для одновременного построения и инициализации есть метод Builder.BuildAndInit(); ### Внедрение зависимостей -Фреймворк реализует внедрение зависимостей для систем. это процесс который запускается вместе с инициализацией пайплайна и внедряет данные переданные в Builder. +Фреймворк реализует внедрение зависимостей для систем. Это процесс, который запускается вместе с инициализацией пайплайна и внедряет данные, переданные в Builder. -``` c# +```c# class SomeDataA { /* ... */ } class SomeDataB : SomeDataA { /* ... */ } @@ -325,7 +323,7 @@ class SomeSystem : IEcsInject, IEcsRun ### Модули Группы систем реализующие общую фичу можно объединять в модули, и просто добавлять модули в Pipeline. -``` c# +```c# using DCFApixels.DragonECS; class Module1 : IEcsModule { @@ -338,7 +336,7 @@ class Module1 : IEcsModule } } ``` -``` c# +```c# EcsPipeline pipeline = EcsPipeline.New() // ... .AddModule(new Module1()) @@ -347,10 +345,10 @@ EcsPipeline pipeline = EcsPipeline.New() ``` ### Сортировка -Дла управления расположением систем в пайплайне, вне зависимости от порядка добавления, есть 2 способа: Слои и Порядок сортировки. +Для управления расположением систем в пайплайне, вне зависимости от порядка добавления, есть 2 способа: Слои и Порядок сортировки. #### Слои Слой определяет место в пайплайне для вставки систем. Например, если необходимо чтобы система была вставлена в конце пайплайна, эту систему можно добавить в слой `EcsConsts.END_LAYER`. -``` c# +```c# const string SOME_LAYER = nameof(SOME_LAYER); EcsPipeline pipeline = EcsPipeline.New() // ... @@ -362,14 +360,14 @@ EcsPipeline pipeline = EcsPipeline.New() .BuildAndInit(); ``` Встроенные слои расположены в следующем порядке: -* `EcsConst.PRE_BEGIN_LAYER` -* `EcsConst.BEGIN_LAYER` -* `EcsConst.BASIC_LAYER` (По умолчанию системы добавляются сюда) -* `EcsConst.END_LAYER` -* `EcsConst.POST_END_LAYER` +* `EcsConsts.PRE_BEGIN_LAYER` +* `EcsConsts.BEGIN_LAYER` +* `EcsConsts.BASIC_LAYER` (По умолчанию системы добавляются сюда) +* `EcsConsts.END_LAYER` +* `EcsConsts.POST_END_LAYER` #### Порядок сортировки Для сортировки систем в рамках слоя используется int значение порядка сортировки. По умолчанию системы добавляются с `sortOrder = 0`. -``` c# +```c# EcsPipeline pipeline = EcsPipeline.New() // ... // Система SomeSystem будет вставлена в слой EcsConsts.BEGIN_LAYER @@ -395,7 +393,7 @@ EcsPipeline pipeline = EcsPipeline.New() Пользовательские процессы Для добавления нового процесса создайте интерфейс наследованный от `IEcsProcess` и создайте раннер для него. Раннер это класс реализующий интерфейс запускаемого процесса и наследуемый от `EcsRunner`. Пример: -``` c# +```c# // Интерфейс процесса. interface IDoSomethingProcess : IEcsProcess { @@ -421,10 +419,10 @@ _pipeline = EcsPipeline.New() .BuildAndInit(); // Запуск раннера если раннер был добавлен. -_pipeline.GetRunner.Do() +_pipeline.GetRunner().Do(); -// Или если раннер не был добавлен(Вызов GetRunnerInstance так же добавит раннер в пайплайн). -_pipeline.GetRunnerInstance.Do() +// Или если раннер не был добавлен (вызов GetRunnerInstance также добавит раннер в пайплайн). +_pipeline.GetRunnerInstance().Do(); ```
@@ -541,9 +539,9 @@ poses.Del(entityID); Обычно маски не используются в чистом виде, а являются частью [Аспекта](#Аспект). -``` c# -// Создание маски с улосвием наличия компонентов SomeCmp1 и SomeCmp2, -// и с улосвием отсутсвия компонента SomeCmp3. +```c# +// Создание маски с условием наличия компонентов SomeCmp1 и SomeCmp2, +// и с условием отсутствия компонента SomeCmp3. EcsMask mask = EcsMask.New(_world) // Inc - Условие наличия компонента. .Inc() @@ -704,7 +702,7 @@ public class SomeDamageSystem : IEcsRun, IEcsInject ``` c# // Запрос Where возвращает сущности в виде EcsSpan. EcsSpan es = _world.Where(out Aspect a); -// Итерироваться можно по foreach и for. +// Итерироваться можно с помощью `foreach` и `for`. foreach (var e in es) { // ... @@ -737,7 +735,7 @@ group.Remove(entityID); ``` c# // Запрос WhereToGroup возвращает сущности в виде группы только для чтения EcsReadonlyGroup. EcsReadonlyGroup group = _world.WhereToGroup(out Aspect a); -// Итерироваться можно по foreach и for. +// Итерироваться можно с помощью `foreach` и `for`. foreach (var e in group) { // ... @@ -963,7 +961,7 @@ using (_marker.Auto()) + `DRAGONECS_STABILITY_MODE` - включает опускаемые в релизном билде проверки. + `DRAGONECS_DISABLE_CATH_EXCEPTIONS` - Выключает поведение по умолчанию по обработке исключений. По умолчанию фреймворк будет ловить исключения с выводом информации из исключений через EcsDebug и продолжать работу. + `REFLECTION_DISABLED` - Полностью ограничивает работу фреймворка с Reflection. -+ `DISABLE_DEBUG` - Для среды где не поддерживается ручное отключение DEBUG, например Unity. ++ `DISABLE_DEBUG` - Для среды, где не поддерживается ручное отключение DEBUG, например Unity.
@@ -1124,7 +1122,7 @@ public struct WorldComponent : IEcsWorldComponent # FAQ ## Как Выключать/Включать системы? -Напрямую - никак.
+Напрямую — никак. Обычно потребность выключить/включить систему появляется когда поменялось общее состояние игры, это может так же значить что нужно переключить сразу группу систем, все это в совокупности можно рассматривать как изменения процессов. Есть 2 решения:
+ Если изменения процесса глобальные, то создать новый `EcsPipeline` и в цикле обновления движка запускать соответствующий пайплайн. + Разделить `IEcsRun` на несколько процессов и в цикле обновления движка запускать соответствующий процесс. Для этого создайте новый интерфейс процесса, раннер для запуска этого интерфейса и получайте раннер через `EcsPipeline.GetRunner()`. diff --git a/README-ZH.md b/README-ZH.md index 6e6777c..27dd568 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -20,19 +20,19 @@ -
+
Русский
-
+
English
-
+
中文
@@ -52,6 +52,7 @@ DragonECS 是一个[实体组件系统](https://www.imooc.com/article/331544)框 ## 目录 - [安装](#安装) +- [扩展](#扩展) - [基础概念](#基础概念) - [实体](#实体) - [组件](#组件) @@ -79,7 +80,6 @@ DragonECS 是一个[实体组件系统](https://www.imooc.com/article/331544)框 - [世界组件](#世界组件) - [配置](#配置) - [使用DragonECS的项目](#使用dragonecs的项目) -- [扩展](#扩展) - [FAQ](#faq) - [反馈](#反馈) @@ -89,14 +89,14 @@ DragonECS 是一个[实体组件系统](https://www.imooc.com/article/331544)框 版本的语义 [[打开]](https://gist.github.com/DCFApixels/e53281d4628b19fe5278f3e77a7da9e8#file-dcfapixels_versioning_ru-md) ## 环境 必备要求: -+ C# 7.3 的最低版本; +* 最低 C# 版本:7.3。 可选要求: -+ 支持NativeAOT; -+ 使用 C# 的游戏引擎:Unity、Godot、MonoGame等。 +* 支持 NativeAOT; +* 使用 C# 的游戏引擎:Unity、Godot、MonoGame 等。 -已测试: -+ **Unity:** 最低版本 2020.1.0; +已测试: +* **Unity:** 最低版本 2021.2.0。 ## 为Unity安装 > 还建议安装[Unity引擎集成](https://github.com/DCFApixels/DragonECS-Unity)扩展。 @@ -108,14 +108,32 @@ https://github.com/DCFApixels/DragonECS.git * ### 作为源代码 框架也可以通过复制源代码添加到项目中。 -
+ +# 扩展 +* 集成: + * [Unity](https://github.com/DCFApixels/DragonECS-Unity) + * [Godot](https://gitlab.com/InauniusOwn/Libraries/DraGodot) +* 包: + * [自动依赖注入](https://github.com/DCFApixels/DragonECS-AutoInjections) + * [经典C#多线程](https://github.com/DCFApixels/DragonECS-ClassicThreads) + * [Recursivity](https://github.com/DCFApixels/DragonECS-Recursivity) + * [Hybrid](https://github.com/DCFApixels/DragonECS-Hybrid) + * [Graphs](https://github.com/DCFApixels/DragonECS-Graphs) +* 工具: + * [简单语法](https://gist.github.com/DCFApixels/d7bfbfb8cb70d141deff00be24f28ff0) + * [EcsRefPool](https://gist.github.com/DCFApixels/73e392ccabdd98b3d4a517017d8a3f22) + * [计时器](https://gist.github.com/DCFApixels/71a416275660c465ece76242290400df) + * [单帧组件](https://gist.github.com/DCFApixels/46d512dbcf96c115b94c3af502461f60) + * [IDE代码模板](https://gist.github.com/ctzcs/0ba948b0e53aa41fe1c87796a401660b) 和 [Unity 模板](https://gist.github.com/ctzcs/d4c7730cf6cd984fe6f9e0e3f108a0f1) +> *你的扩展?如果你正在开发 DragonECS 的扩展,可以[在此处发布](#反馈). + # 基础概念 ## 实体 -**实体**是附加数据的基础。它们以标识符的形式实现,有两种类型: -* `int` - 是在单个更新中使用的一次性标识符。不建议存储`int`标识符,而应使用 `entlong`; -* `entlong` - 是一个长期标识符,包含一整套用于明确识别的信息; -``` c# +**实体**是附加数据的基础。有两种用于引用实体的标识符: +* `int` - 短期标识符,仅在单次更新(tick)内有效。不建议用于长期存储; +* `entlong` - 长期标识符,包含一个世代标记(generation tag),使其在实体的整个生命周期内保持唯一。适合长期保存和存储使用; +```c# // 在世界中创建一个新实体。 int entityID = _world.NewEntity(); @@ -132,7 +150,7 @@ int newEntityID = _world.CloneEntity(entityID);
entlong使用 -``` c# +```c# // int 转换为 entlong。 entlong entity = _world.GetEntityLong(entityID); // 或者 @@ -220,7 +238,7 @@ class SomeSystem : IEcsRun, IEcsPipelineMember ### 依赖注入 框架具有向系统注入依赖的功能。这是一个与管线初始化一起运行的流程,并注入传递给Builder的数据。 > 内置依赖注入的使用是可选的。 -``` c# +```c# class SomeDataA { /* ... */ } class SomeDataB : SomeDataA { /* ... */ } @@ -251,9 +269,15 @@ class SomeSystem : IEcsInject, IEcsRun } ``` +静态标记的含义: +* `Inc` — 组件必须存在(包含条件)并缓存该池。 +* `Exc` — 组件不得存在(排除条件)并缓存该池。 +* `Opt` — 组件可以存在,但不影响过滤(仅缓存池以便访问)。 +* `Any` — 至少要存在被 `Any` 标记的组件之一;同时缓存该池。 + ### 模块 实现一个共同特性的系统组可以组合成模块,模块也可以简单地添加到管线中。 -``` c# +```c# using DCFApixels.DragonECS; class Module1 : IEcsModule { @@ -290,11 +314,11 @@ EcsPipeline pipeline = EcsPipeline.New() .BuildAndInit(); ``` 嵌入层按以下顺序排列: -* `EcsConst.PRE_BEGIN_LAYER` -* `EcsConst.BEGIN_LAYER` -* `EcsConst.BASIC_LAYER`(默认情况下,系统添加到此层) -* `EcsConst.END_LAYER` -* `EcsConst.POST_END_LAYER` +* `EcsConsts.PRE_BEGIN_LAYER` +* `EcsConsts.BEGIN_LAYER` +* `EcsConsts.BASIC_LAYER`(默认情况下,系统添加到此层) +* `EcsConsts.END_LAYER` +* `EcsConsts.POST_END_LAYER` #### 排序顺序 在同一层内,可以使用 `int` 类型的排序值来排序系统。默认情况下,系统的排序值为 `sortOrder = 0`。 ```c# @@ -322,7 +346,7 @@ EcsPipeline pipeline = EcsPipeline.New()
用户流程 -Для добавления нового процесса создайте интерфейс наследованный от `IEcsProcess` и создайте раннер для него. Раннер это класс реализующий интерфейс запускаемого процесса и наследуемый от `EcsRunner`. Пример: +要添加新的流程,请创建一个继承自 `IEcsProcess` 的接口,并为其创建一个 Runner。Runner 是一个实现该流程接口并继承自 `EcsRunner` 的类。示例: ``` c# // 流程接口。 interface IDoSomethingProcess : IEcsProcess @@ -347,10 +371,10 @@ _pipeline = EcsPipeline.New() .BuildAndInit(); // 如果启动器已经添加,运行它。 -_pipeline.GetRunner.Do() +_pipeline.GetRunner().Do(); // 如果启动器尚未添加,使用 GetRunnerInstance 将其添加并运行 -_pipeline.GetRunnerInstance.Do() +_pipeline.GetRunnerInstance().Do(); ```
@@ -437,7 +461,7 @@ poses.Del(entityID); > 可以实现用户池。稍后将介绍这一功能。 ## 掩码 -用于根据组件的存在与否来过滤实体。 +用于根据组件的存在与否来过滤实体。通常掩码不单独使用,而是作为 `EcsAspect` 的一部分,用于查询时过滤实体。 ``` c# // 创建一个掩码,检查实体是否具有组件 // SomeCmp1 和 SomeCmp2,但没有组件 SomeCmp3。 @@ -472,7 +496,11 @@ EcsMask mask = _staticMask.ToMask(_world);
## 方面 -这些是继承自 EcsAspect 的用户类,用于与实体进行交互。方面同时充当池的缓存和实体组件的过滤掩码。可以把方面视为系统处理哪些实体的描述。 +方面是继承自 `EcsAspect` 的用户自定义类,用于描述系统要处理的一组组件。方面同时承担两个职责: +- 掩码 — 初始化并保存一个 `EcsMask`,使其可在查询中用于过滤实体。 +- 池缓存 — 提供对组件池的快速访问。 + +简而言之,方面是描述“我处理哪些实体以及如何访问它们的组件”的便捷方式。 简化语法: ``` c# @@ -503,9 +531,9 @@ class Aspect : EcsAspect public EcsPool velocities; protected override void Init(Builder b) { - poses = b.Include(); - velocities = b.Include(); - b.Exclude(); + poses = b.Inc(); + velocities = b.Inc(); + b.Exc(); } } ``` @@ -529,13 +557,13 @@ class Aspect : EcsAspect otherAspect1 = b.Combine(1); // 即使对 OtherAspect1 调用 Combine 方法更早,Aspect 会首先与 OtherAspect2 进行组合,因为默认情况下 order = 0。 otherAspect2 = b.Combine(); - // 如果 OtherAspect1 或 OtherAspect2 中有 b.Exclude() 的限制条件,这里将被替换为 b.Include()。 - poses = b.Include(); + // 如果 OtherAspect1 或 OtherAspect2 中有 b.Exc() 的限制条件,这里将被替换为 b.Inc(). + poses = b.Inc(); } } ``` 如果组合的方面存在冲突的限制条件,则新的限制条件将替换先前添加的限制条件。根方面的限制条件始终会替换添加的方面中的限制条件。限制条件组合的视觉示例: -| | cmp1 | cmp2 | cmp3 | cmp4 | cmp5 | разрешение конфликтных ограничений| +| | cmp1 | cmp2 | cmp3 | cmp4 | cmp5 | 冲突限制的解析 | | :--- | :--- | :--- | :--- | :--- | :--- |:--- | | OtherAspect2 | :heavy_check_mark: | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | | | OtherAspect1 | :heavy_minus_sign: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_minus_sign: | 对于 `cmp2` 将选择 :heavy_check_mark: | @@ -978,6 +1006,23 @@ public struct WorldComponent : IEcsWorldComponent ## Released games: + + + + + + +
+ + Crystal Siege + + + + + Order matters + + +
@@ -986,40 +1031,26 @@ public struct WorldComponent : IEcsWorldComponent - - ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ + _____________ screenshot -

-# 扩展 -* Packages: - * [Unity集成](https://github.com/DCFApixels/DragonECS-Unity) - * [自动依赖注入](https://github.com/DCFApixels/DragonECS-AutoInjections) - * [经典C#多线程](https://github.com/DCFApixels/DragonECS-ClassicThreads) - * [Recursivity](https://github.com/DCFApixels/DragonECS-Recursivity) - * [Hybrid](https://github.com/DCFApixels/DragonECS-Hybrid) - * [Graphs](https://github.com/DCFApixels/DragonECS-Graphs) -* Utilities: - * [简单语法](https://gist.github.com/DCFApixels/d7bfbfb8cb70d141deff00be24f28ff0) - * [单帧组件](https://gist.github.com/DCFApixels/46d512dbcf96c115b94c3af502461f60) - * [IDE代码模板](https://gist.github.com/ctzcs/0ba948b0e53aa41fe1c87796a401660b) и [Unity代码模板](https://gist.github.com/ctzcs/d4c7730cf6cd984fe6f9e0e3f108a0f1) - -> *你的扩展?如果你正在开发 DragonECS 的扩展,可以[在此处发布](#反馈). - -
# FAQ -## 'ReadOnlySpan<>' could not be found -在Unity 2020.1.x版本中,控制台可能会出现以下错误: -``` -The type or namespace name 'ReadOnlySpan<>' could not be found (are you missing a using directive or an assembly reference?) -``` -要解决这个问题,需要在`Project Settings/Player/Other Settings/Scripting Define Symbols`中添加`ENABLE_DUMMY_SPAN`指令. + +## 如何启用/禁用系统? +直接——不能。 + +通常当游戏的整体状态发生变化时,会需要启用或禁用系统;有时需要切换一组系统。从概念上讲,这可以视为流程(process)的变更。这里有两种解决方案: + +- 如果流程变更是全局性的,可以创建一个新的 `EcsPipeline`,并在引擎的更新循环中运行相应的管线(pipeline)。 +- 将 `IEcsRun` 拆分为多个流程,并在引擎更新循环中运行所需的流程。为此,创建一个新的流程接口,为其实现一个 Runner,并通过 `EcsPipeline.GetRunner()` 获取该 Runner。 + +## 建议清单: [DragonECS-Vault](https://github.com/DCFApixels/DragonECS-Vault)
# 反馈 diff --git a/README.md b/README.md index c3f9193..f6c1583 100644 --- a/README.md +++ b/README.md @@ -22,26 +22,26 @@ -
+
Русский
-
+
English
-
+
中文
-
+ The [ECS](https://en.wikipedia.org/wiki/Entity_component_system) Framework aims to maximize usability, modularity, extensibility and performance of dynamic entity changes. Without code generation and dependencies. Inspired by [LeoEcs Lite](https://github.com/Leopotam/ecslite). @@ -54,6 +54,7 @@ The [ECS](https://en.wikipedia.org/wiki/Entity_component_system) Framework aims ## Table of Contents - [Installation](#installation) +- [Extensions](#extensions) - [Basic Concepts](#basic-concepts) - [Entity](#entity) - [Component](#component) @@ -91,14 +92,14 @@ The [ECS](https://en.wikipedia.org/wiki/Entity_component_system) Framework aims Versioning semantics - [Open](https://gist.github.com/DCFApixels/e53281d4628b19fe5278f3e77a7da9e8#file-dcfapixels_versioning_ru-md) ## Environment Requirements: -+ Minimum version of C# 7.3; - +* Minimum C# version: 7.3. + Optional: -+ Support for NativeAOT -+ Game engines with C#: Unity, Godot, MonoGame, etc. - +* Support for NativeAOT +* Game engines with C#: Unity, Godot, MonoGame, etc. + Tested with: -+ **Unity:** Minimum version 2020.1.0; +* **Unity:** Minimum version 2021.2.0. ## Unity Installation * ### Unity Package @@ -109,14 +110,32 @@ https://github.com/DCFApixels/DragonECS.git * ### Source Code The framework can also be added to the project as source code. -
+ +# Extensions +* Integrations: + * [Unity](https://github.com/DCFApixels/DragonECS-Unity) + * [Godot](https://gitlab.com/InauniusOwn/Libraries/DraGodot) +* Packages: + * [Dependency autoinjections](https://github.com/DCFApixels/DragonECS-AutoInjections) + * [Classic C# multithreading](https://github.com/DCFApixels/DragonECS-ClassicThreads) + * [Recursivity](https://github.com/DCFApixels/DragonECS-Recursivity) + * [Hybrid](https://github.com/DCFApixels/DragonECS-Hybrid) + * [Graphs](https://github.com/DCFApixels/DragonECS-Graphs) +* Utilities: + * [Simple syntax](https://gist.github.com/DCFApixels/d7bfbfb8cb70d141deff00be24f28ff0) + * [EcsRefPool](https://gist.github.com/DCFApixels/73e392ccabdd98b3d4a517017d8a3f22) + * [Timers](https://gist.github.com/DCFApixels/71a416275660c465ece76242290400df) + * [One-Frame Components](https://gist.github.com/DCFApixels/46d512dbcf96c115b94c3af502461f60) + * [Code Templates for IDE](https://gist.github.com/ctzcs/0ba948b0e53aa41fe1c87796a401660b) and [for Unity](https://gist.github.com/ctzcs/d4c7730cf6cd984fe6f9e0e3f108a0f1) +> *Your extension? If you are developing an extension for DragonECS, you can share it [here](#feedback). + # Basic Concepts ## Entity -Сontainer for components. They are implemented as identifiers, of which there are two types: -* `int` - a short-term identifier used within a single tick. Storing `int` identifiers is not recommended, use `entlong` instead; -* `entlong` - long-term identifier, contains a full set of information for unique identification; -``` c# +Container for components. There are two identifier types used to reference entities: +* `int` - short-lived identifier, valid within a single tick. Not recommended for long-term storage; +* `entlong` - long-term identifier that includes a generation tag, which makes it unique across entity lifetimes. Suitable for storing and long-term usage. +```c# // Creating a new entity in the world. int entityID = _world.NewEntity(); @@ -133,7 +152,7 @@ int newEntityID = _world.CloneEntity(entityID);
Working with entlong -``` c# +```c# // Convert int to entlong. entlong entity = _world.GetEntityLong(entityID); // or @@ -222,7 +241,7 @@ class SomeSystem : IEcsRun, IEcsPipelineMember ### Dependency Injection The framework implements dependency injection for systems. This process begins during pipeline initialization and injects data passed to the Builder. > Using built-in dependency injection is optional. -``` c# +```c# class SomeDataA { /* ... */ } class SomeDataB : SomeDataA { /* ... */ } @@ -257,7 +276,7 @@ class SomeSystem : IEcsInject, IEcsRun ### Modules Groups of systems that implement a common feature can be grouped into modules and easily added to the Pipeline. -``` c# +```c# using DCFApixels.DragonECS; class Module1 : IEcsModule { @@ -294,11 +313,11 @@ EcsPipeline pipeline = EcsPipeline.New() .BuildAndInit(); ``` The built-in layers are arranged in the following order: -* `EcsConst.PRE_BEGIN_LAYER` -* `EcsConst.BEGIN_LAYER` -* `EcsConst.BASIC_LAYER` (Systems are added here if no layer is specified during addition) -* `EcsConst.END_LAYER` -* `EcsConst.POST_END_LAYER` +* `EcsConsts.PRE_BEGIN_LAYER` +* `EcsConsts.BEGIN_LAYER` +* `EcsConsts.BASIC_LAYER` (Systems are added here if no layer is specified during addition) +* `EcsConsts.END_LAYER` +* `EcsConsts.POST_END_LAYER` #### Sorting Order The sort order int value is used to sort systems within a layer. By default, systems are added with `sortOrder = 0`. @@ -352,10 +371,10 @@ _pipeline = EcsPipeline.New() .BuildAndInit(); // Running the runner if it was added -_pipeline.GetRunner.Do() +_pipeline.GetRunner().Do(); // or if the runner was not added (calling GetRunnerInstance will also add the runner to the pipeline). -_pipeline.GetRunnerInstance.Do() +_pipeline.GetRunnerInstance().Do(); ```
@@ -444,7 +463,7 @@ poses.Del(entityID); > It is possible to implement a user pool. This feature will be described shortly. ## Mask -Used to filter entities by the presence or absence of components. +Used to filter entities by the presence or absence of components. Usually masks are not used standalone, they are part of `EcsAspect` and used by queries to filter entities. ``` c# // Creating a mask that checks if entities have components // SomeCmp1 and SomeCmp2, but do not have component SomeCmp3. @@ -479,7 +498,11 @@ EcsMask mask = _staticMask.ToMask(_world);
## Aspect -These are custom classes inherited from `EcsAspect` and used to interact with entities. Aspects are both a pool cache and a component mask for filtering entities. You can think of aspects as a description of what entities the system is working with. +These are user-defined classes that inherit from `EcsAspect` and describe sets of components a system works with. An aspect serves two purposes: +- Mask — initializes and holds an `EcsMask`, so it can be used in queries to filter entities. +- Pool cache — provides fast access to component pools. + +In short, an aspect is a convenient way to declare "which entities I work with and how to access their components." Simplified syntax: ``` c# @@ -500,6 +523,13 @@ class Aspect : EcsAspect } ``` +Purpose of the static markers: +* `Inc` — component must be present (inclusive) and caches the pool. +* `Exc` — component must NOT be present (exclusive) and caches the pool. +* `Opt` — component may be present, but does not affect filtering (only caches the pool for access). +* `Any` — at least one of the components marked with `Any` must be present; caches the pool. + + Explicit syntax (the result is identical to the example above): ``` c# using DCFApixels.DragonECS; @@ -510,9 +540,9 @@ class Aspect : EcsAspect public EcsPool velocities; protected override void Init(Builder b) { - poses = b.Include(); - velocities = b.Include(); - b.Exclude(); + poses = b.Inc(); + velocities = b.Inc(); + b.Exc(); } } ``` @@ -536,17 +566,17 @@ class Aspect : EcsAspect otherAspect1 = b.Combine(1); // Although Combine was called earlier for OtherAspect1, it will first combine with OtherAspect2 because the default order is 0. otherAspect2 = b.Combine(); - // If b.Exclude() was specified in OtherAspect1 or OtherAspect2, it will be replaced with b.Include() here. - poses = b.Include(); + // If b.Exc() was specified in OtherAspect1 or OtherAspect2, it will be replaced with b.Inc() here. + poses = b.Inc(); } } ``` If there are conflicting constraints between the combined aspects, the new constraints will replace those added earlier. Constraints from the root aspect always replace constraints from added aspects. Here's a visual example of constraint combination: -| | cmp1 | cmp2 | cmp3 | cmp4 | cmp5 | разрешение конфликтных ограничений| +| | cmp1 | cmp2 | cmp3 | cmp4 | cmp5 | Conflict resolution | | :--- | :--- | :--- | :--- | :--- | :--- |:--- | | OtherAspect2 | :heavy_check_mark: | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | | -| OtherAspect1 | :heavy_minus_sign: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_minus_sign: | For `cmp2` will be chosen. :heavy_check_mark: | -| Aspect | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | For `cmp1` will be chosen. :x: | +| OtherAspect1 | :heavy_minus_sign: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_minus_sign: | For `cmp2`, :heavy_check_mark: will be chosen. | +| Aspect | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | For `cmp1`, :x: will be chosen. | | Final Constraints | :x: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_check_mark: | |
@@ -984,6 +1014,23 @@ public struct WorldComponent : IEcsWorldComponent ## Released games: + + + + + + +
+ + Crystal Siege + + + + + Order matters + + +
@@ -992,40 +1039,26 @@ public struct WorldComponent : IEcsWorldComponent - - ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ + _____________ screenshot -

-# Extensions -* Packages: - * [Unity integration](https://github.com/DCFApixels/DragonECS-Unity) - * [Dependency autoinjections](https://github.com/DCFApixels/DragonECS-AutoInjections) - * [Classic C# multithreading](https://github.com/DCFApixels/DragonECS-ClassicThreads) - * [Recursivity](https://github.com/DCFApixels/DragonECS-Recursivity) - * [Hybrid](https://github.com/DCFApixels/DragonECS-Hybrid) - * [Graphs](https://github.com/DCFApixels/DragonECS-Graphs) -* Utilities: - * [Simple syntax](https://gist.github.com/DCFApixels/d7bfbfb8cb70d141deff00be24f28ff0) - * [One-Frame Components](https://gist.github.com/DCFApixels/46d512dbcf96c115b94c3af502461f60) - * [Code Templates for IDE](https://gist.github.com/ctzcs/0ba948b0e53aa41fe1c87796a401660b) and [for Unity](https://gist.github.com/ctzcs/d4c7730cf6cd984fe6f9e0e3f108a0f1) -> *Your extension? If you are developing an extension for DragonECS, you can share it [here](#feedback). - -
# FAQ -## 'ReadOnlySpan<>' could not be found -In Unity 2020.1.x, you may encounter this error in the console: -``` -The type or namespace name 'ReadOnlySpan<>' could not be found (are you missing a using directive or an assembly reference?) -``` -To fix this, add the define symbol `ENABLE_DUMMY_SPAN` to `Project Settings/Player/Other Settings/Scripting Define Symbols`. +## How to enable/disable systems? +Directly — you can't. + +The need to enable or disable systems usually appears when the overall game state changes; this may also mean switching a group of systems. Conceptually this is a change of processes. There are two solutions: + +- If the process changes are global, create a new `EcsPipeline` and run the appropriate pipeline in the engine update loop. +- Split `IEcsRun` into multiple processes and run the desired process in the engine update loop. To do this create a new process interface, implement a runner for it, and obtain the runner via `EcsPipeline.GetRunner()`. + +## Recommendations list: [DragonECS-Vault](https://github.com/DCFApixels/DragonECS-Vault)
# Feedback