From 7b75720999eb6100471bc7ea733155356af900a2 Mon Sep 17 00:00:00 2001 From: Karpik Date: Mon, 2 Mar 2026 20:11:19 +0400 Subject: [PATCH 1/6] Add static method to clear static fields --- src/DebugUtils/TypeMeta.cs | 8 ++++++++ src/EcsAspect.cs | 5 +++++ src/EcsStaticCleaner.cs | 18 ++++++++++++++++++ src/EcsWorld.static.cs | 5 +++++ src/Injections/Injector.cs | 6 ++++++ src/Internal/EcsTypeCodeManager.cs | 5 +++++ src/Utils/IConfigContainer.cs | 5 +++++ 7 files changed, 52 insertions(+) create mode 100644 src/EcsStaticCleaner.cs diff --git a/src/DebugUtils/TypeMeta.cs b/src/DebugUtils/TypeMeta.cs index 7c3d8c9..1f8ad7b 100644 --- a/src/DebugUtils/TypeMeta.cs +++ b/src/DebugUtils/TypeMeta.cs @@ -623,5 +623,13 @@ namespace DCFApixels.DragonECS #endregion } #endregion + + internal static void Clear() + { + lock (_lock) + { + _metaCache.Clear(); + } + } } } \ No newline at end of file diff --git a/src/EcsAspect.cs b/src/EcsAspect.cs index 75a3be2..15aeb18 100644 --- a/src/EcsAspect.cs +++ b/src/EcsAspect.cs @@ -467,6 +467,11 @@ namespace DCFApixels.DragonECS public delegate void OnBuildApectHandler(object aspect, EcsMask mask); public static event OnBuildApectHandler OnAfterInit = delegate { }; #endregion + + internal static void Clear() + { + _staticMaskCache.Clear(); + } } #region EcsAspect.Builder.Extensions diff --git a/src/EcsStaticCleaner.cs b/src/EcsStaticCleaner.cs new file mode 100644 index 0000000..6007943 --- /dev/null +++ b/src/EcsStaticCleaner.cs @@ -0,0 +1,18 @@ +using DCFApixels.DragonECS.Core.Internal; + +namespace DCFApixels.DragonECS +{ + public static class EcsStaticCleaner + { + public static void ResetAll() + { + TypeMeta.Clear(); + Injector.InjectionList.Clear(); + // MemoryAllocator.Clear(); + EcsTypeCodeManager.Clear(); + ConfigContainer.Clear(); + EcsAspect.Clear(); + EcsWorld.Clear(); + } + } +} \ No newline at end of file diff --git a/src/EcsWorld.static.cs b/src/EcsWorld.static.cs index 033321a..c9b94cf 100644 --- a/src/EcsWorld.static.cs +++ b/src/EcsWorld.static.cs @@ -346,5 +346,10 @@ namespace DCFApixels.DragonECS return FindPoolInstance(componentType); } #endregion + + internal static void Clear() + { + _allWorldComponentPools.Clear(); + } } } \ No newline at end of file diff --git a/src/Injections/Injector.cs b/src/Injections/Injector.cs index df558b0..c68c965 100644 --- a/src/Injections/Injector.cs +++ b/src/Injections/Injector.cs @@ -357,6 +357,12 @@ namespace DCFApixels.DragonECS instance.Inject(_injectedData); } } + + internal static void Clear() + { + _Empty_Internal._injections.Clear(); + _Empty_Internal._nodes.Clear(); + } } #endregion } diff --git a/src/Internal/EcsTypeCodeManager.cs b/src/Internal/EcsTypeCodeManager.cs index ea902a1..b2c2041 100644 --- a/src/Internal/EcsTypeCodeManager.cs +++ b/src/Internal/EcsTypeCodeManager.cs @@ -53,6 +53,11 @@ namespace DCFApixels.DragonECS.Core.Internal return null; } public static IEnumerable GetDeclaredTypes() { return _codes.Select(o => new TypeCodeInfo(o.Key, o.Value)); } + + internal static void Clear() + { + _codes.Clear(); + } } #if ENABLE_IL2CPP [Il2CppSetOption(Option.NullChecks, false)] diff --git a/src/Utils/IConfigContainer.cs b/src/Utils/IConfigContainer.cs index 98192f0..b5a6103 100644 --- a/src/Utils/IConfigContainer.cs +++ b/src/Utils/IConfigContainer.cs @@ -102,6 +102,11 @@ namespace DCFApixels.DragonECS { return GetAllConfigs().GetEnumerator(); } + + internal static void Clear() + { + Empty._storage.Clear(); + } } public static class ConfigContainerExtensions { From 9bd7558bdd495974d48329b1040b272de1d8f06d Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Tue, 3 Mar 2026 15:04:23 +0800 Subject: [PATCH 2/6] Squashed commit of the following: commit 6452850ff8c7ea5983dbd6a79b5a836ed6eb3072 Author: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Tue Mar 3 14:46:58 2026 +0800 improve entities cleanup commit db6b1d209aab5a7abd286eb84898f5ad838277a5 Author: Karpik Date: Tue Jan 27 22:46:58 2026 +0400 Remove components for every entity in world.Destroy() In my situation, it invokes IEcsComponentLifecycle methods --- src/EcsWorld.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 2ce52bb..b7fcbdf 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -234,6 +234,12 @@ namespace DCFApixels.DragonECS #endif return; } + + for (int i = Entities.Count - 1; i >= 0; i--) + { + DelEntity(Entities[i]); + } + _isDestroyed = true; _listeners.InvokeOnWorldDestroy(); _entityDispenser = null; @@ -253,7 +259,6 @@ namespace DCFApixels.DragonECS //_entities - не обнуляется для работы entlong.IsAlive } } - //public void Clear() { } #endregion #region Getters From 4a89f2a4a549a1a78fcdbf747f2a5110126c93a6 Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Tue, 3 Mar 2026 15:15:16 +0800 Subject: [PATCH 3/6] fix --- src/EcsWorld.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index b7fcbdf..ef35fd8 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -239,6 +239,7 @@ namespace DCFApixels.DragonECS { DelEntity(Entities[i]); } + ReleaseDelEntityBufferAll(); _isDestroyed = true; _listeners.InvokeOnWorldDestroy(); From b6ae601cff3dffbc287d242beb42bc62e606a8ae Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Wed, 4 Mar 2026 14:00:52 +0800 Subject: [PATCH 4/6] fix/improve static cleanup --- src/DebugUtils/TypeMeta.cs | 16 ++++++++-------- src/EcsAspect.cs | 9 ++++----- src/EcsStaticCleaner.cs | 18 ------------------ src/EcsWorld.cs | 4 ---- src/EcsWorld.static.cs | 10 +--------- src/Internal/EcsTypeCodeManager.cs | 5 ----- src/Utils/IConfigContainer.cs | 5 ----- 7 files changed, 13 insertions(+), 54 deletions(-) delete mode 100644 src/EcsStaticCleaner.cs diff --git a/src/DebugUtils/TypeMeta.cs b/src/DebugUtils/TypeMeta.cs index 1f8ad7b..0422993 100644 --- a/src/DebugUtils/TypeMeta.cs +++ b/src/DebugUtils/TypeMeta.cs @@ -370,6 +370,14 @@ namespace DCFApixels.DragonECS #endregion #region Other + public static void ClearCache() + { + lock (_lock) + { + _metaCache.Clear(); + _metaCache.Add(typeof(void), NullTypeMeta); + } + } ITypeMeta ITypeMeta.BaseMeta { get { return null; } @@ -623,13 +631,5 @@ namespace DCFApixels.DragonECS #endregion } #endregion - - internal static void Clear() - { - lock (_lock) - { - _metaCache.Clear(); - } - } } } \ No newline at end of file diff --git a/src/EcsAspect.cs b/src/EcsAspect.cs index 15aeb18..0a2afc9 100644 --- a/src/EcsAspect.cs +++ b/src/EcsAspect.cs @@ -411,6 +411,10 @@ namespace DCFApixels.DragonECS #endregion #region Other + public static void ClearCache() + { + _staticMaskCache.Clear(); + } EcsMask IComponentMask.ToMask(EcsWorld world) { return _mask; } #endregion @@ -467,11 +471,6 @@ namespace DCFApixels.DragonECS public delegate void OnBuildApectHandler(object aspect, EcsMask mask); public static event OnBuildApectHandler OnAfterInit = delegate { }; #endregion - - internal static void Clear() - { - _staticMaskCache.Clear(); - } } #region EcsAspect.Builder.Extensions diff --git a/src/EcsStaticCleaner.cs b/src/EcsStaticCleaner.cs deleted file mode 100644 index 6007943..0000000 --- a/src/EcsStaticCleaner.cs +++ /dev/null @@ -1,18 +0,0 @@ -using DCFApixels.DragonECS.Core.Internal; - -namespace DCFApixels.DragonECS -{ - public static class EcsStaticCleaner - { - public static void ResetAll() - { - TypeMeta.Clear(); - Injector.InjectionList.Clear(); - // MemoryAllocator.Clear(); - EcsTypeCodeManager.Clear(); - ConfigContainer.Clear(); - EcsAspect.Clear(); - EcsWorld.Clear(); - } - } -} \ No newline at end of file diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 2ce52bb..c59d9cb 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -175,10 +175,6 @@ namespace DCFApixels.DragonECS // тут сложно однозначно посчитать, так как нужно еще место под аспекты и запросы int controllersCount = config.PoolsCapacity * 4; _worldComponentPools = new StructList(controllersCount); - if (controllersCount < _allWorldComponentPools.Capacity) - { - _allWorldComponentPools.Capacity = controllersCount; - } if (worldID < 0 || (worldID == NULL_WORLD_ID && nullWorld == false)) { diff --git a/src/EcsWorld.static.cs b/src/EcsWorld.static.cs index c9b94cf..91699e1 100644 --- a/src/EcsWorld.static.cs +++ b/src/EcsWorld.static.cs @@ -147,10 +147,7 @@ namespace DCFApixels.DragonECS private static short _recycledItemsCount; private static readonly IEcsWorldComponent _interface = EcsWorldComponentHandler.instance; private static readonly Abstract _controller = new Abstract(); - static WorldComponentPool() - { - _allWorldComponentPools.Add(_controller); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T GetItem(int itemIndex) {// ts @@ -346,10 +343,5 @@ namespace DCFApixels.DragonECS return FindPoolInstance(componentType); } #endregion - - internal static void Clear() - { - _allWorldComponentPools.Clear(); - } } } \ No newline at end of file diff --git a/src/Internal/EcsTypeCodeManager.cs b/src/Internal/EcsTypeCodeManager.cs index b2c2041..ea902a1 100644 --- a/src/Internal/EcsTypeCodeManager.cs +++ b/src/Internal/EcsTypeCodeManager.cs @@ -53,11 +53,6 @@ namespace DCFApixels.DragonECS.Core.Internal return null; } public static IEnumerable GetDeclaredTypes() { return _codes.Select(o => new TypeCodeInfo(o.Key, o.Value)); } - - internal static void Clear() - { - _codes.Clear(); - } } #if ENABLE_IL2CPP [Il2CppSetOption(Option.NullChecks, false)] diff --git a/src/Utils/IConfigContainer.cs b/src/Utils/IConfigContainer.cs index b5a6103..98192f0 100644 --- a/src/Utils/IConfigContainer.cs +++ b/src/Utils/IConfigContainer.cs @@ -102,11 +102,6 @@ namespace DCFApixels.DragonECS { return GetAllConfigs().GetEnumerator(); } - - internal static void Clear() - { - Empty._storage.Clear(); - } } public static class ConfigContainerExtensions { From 2c11eaa463d62e004f7e14925d6410d50e37182d Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:44:02 +0800 Subject: [PATCH 5/6] update readme --- README-RU.md | 195 +++++++++++++++++++++++++++++++++++---------------- README-ZH.md | 4 +- README.md | 4 +- 3 files changed, 140 insertions(+), 63 deletions(-) diff --git a/README-RU.md b/README-RU.md index 45df20a..b443b71 100644 --- a/README-RU.md +++ b/README-RU.md @@ -19,7 +19,7 @@ - +
Русский
@@ -31,7 +31,7 @@ - +
中文
@@ -50,6 +50,7 @@ DragonECS - это [ECS](https://en.wikipedia.org/wiki/Entity_component_system) ## Оглавление - [Установка](#установка) +- [Расширения](#расширения) - [Основные концепции](#основные-концепции) - [Entity](#entity) - [Component](#component) @@ -77,7 +78,6 @@ DragonECS - это [ECS](https://en.wikipedia.org/wiki/Entity_component_system) - [Компоненты мира](#компоненты-мира) - [Конфиги](#конфиги) - [Проекты на DragonECS](#Проекты-на-DragonECS) -- [Расширения](#расширения) - [FAQ](#faq) - [Обратная связь](#обратная-связь) @@ -94,24 +94,49 @@ DragonECS - это [ECS](https://en.wikipedia.org/wiki/Entity_component_system) + Игровые движки с C#: Unity, Godot, MonoGame и т.д. Протестировано: -+ **Unity:** Минимальная версия 2020.1.0; ++ **Unity:** Минимальная версия 2020.3.0; ## Установка для Unity > Рекомендуется так же установить расширение [Интеграция с движком Unity](https://github.com/DCFApixels/DragonECS-Unity) * ### Unity-модуль -Поддерживается установка в виде Unity-модуля в при помощи добавления git-URL [в PackageManager](https://docs.unity3d.com/2023.2/Documentation/Manual/upm-ui-giturl.html) или ручного добавления в `Packages/manifest.json`: +Поддерживается установка в виде Unity-модуля при помощи добавления git-URL [в PackageManager](https://docs.unity3d.com/2023.2/Documentation/Manual/upm-ui-giturl.html): ``` https://github.com/DCFApixels/DragonECS.git ``` +Или ручного добавления этой строчки в `Packages/manifest.json`: +``` +"com.dcfa_pixels.dragonecs": "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) + * [Графы](https://github.com/DCFApixels/DragonECS-Graphs) +* Утилиты: + * [Упрощенный синтаксис](https://gist.github.com/DCFApixels/d7bfbfb8cb70d141deff00be24f28ff0) + * [Таймеры](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, пиши [сюда](#обратная-связь). +
# Основные концепции ## Entity -**Сущности** - это то к чему крепятся данные. Реализованы в виде идентификаторов, которых есть 2 вида: -* `int` - однократный идентификатор, применяется в пределах одного тика. Не рекомендуется хранить `int` идентификаторы, в место этого используйте `entlong`; -* `entlong` - долговременный идентификатор, содержит в себе полный набор информации для однозначной идентификации; +**Сущности** - это то к чему крепятся данные. Для доступа к сущности используются идентификаторы двух типов: +* `int` - однократный идентификатор, применяется в пределах одного тика. Не рекомендуется использовать для хранения; +* `entlong` - долговременный идентификатор, содержит метку поколения, что делает его уникальным навсегда. Подходит для хранения. ``` c# // Создание новой сущности в мире. int entityID = _world.NewEntity(); @@ -129,10 +154,11 @@ int newEntityID = _world.CloneEntity(entityID);
Работа с entlong + ``` c# // Конвертация int в entlong. entlong entity = _world.GetEntityLong(entityID); -// или +// упрощенная версия entlong entity = (_world, entityID); // Проверка что сущность еще жива. @@ -148,6 +174,8 @@ if (entity.TryGetID(out int entityID)) { } ```
+ +> > Сущности не могут существовать без компонентов, пустые сущности будут автоматически удаляться сразу после удаления последнего компонента либо в конце тика. ## Component @@ -183,6 +211,48 @@ class SomeSystem : IEcsPreInit, IEcsInit, IEcsRun, IEcsDestroy ``` > Для реализации дополнительных процессов перейдите к разделу [Процессы](#Процессы). +
+Пример системы + + +``` c# +// Система +class DamageSystem : IEcsRun, IEcsInject +{ + // Аспекты описаны в соответствующей главе + class Aspect : EcsAspect + { + public EcsPool DamageRequests = Inc; + public EcsPool Healths = Inc; + } + // Мир - хранилище сущностей, так же описан в соответствующей главе + EcsDefaultWorld world; + // Процесс Run + public void Run() + { + // Итерируемся по сущностям, в рамках Run можно использовать int идентификаторы сущностей + foreach (int e in world.Where(out Aspect a)) + { + // Логика нанесения урона + a.Healths[e].Points -= a.DamageRequests[e].Points; + } + } + // Процесс Inject. Получение инстанса EcsDefaultWorld + void IEcsInject.Inject(EcsDefaultWorld obj) => world = obj; +} +// Компоненты +public struct DamageRequest : IEcsComponent +{ + public float Points; +} +public struct Health : IEcsComponent +{ + public float Points; +} +``` + +
+
# Концепции фреймворка @@ -466,10 +536,13 @@ poses.Del(entityID); ## Маска -Применяется для фильтрации сущностей по наличию или отсутствию компонентов. +Набор требований к компонентам сущности: какие компоненты должны присутствовать, а какие отсутствовать. Маска — это просто данные, она не выполняет поиск, а используется запросами для фильтрации сущностей. + +Обычно маски не используются в чистом виде, а являются частью [Аспекта](#Аспект). + ``` c# -// Создание маски которая проверяет что у сущностей есть компоненты -// SomeCmp1 и SomeCmp2, но нет компонента SomeCmp3. +// Создание маски с улосвием наличия компонентов SomeCmp1 и SomeCmp2, +// и с улосвием отсутсвия компонента SomeCmp3. EcsMask mask = EcsMask.New(_world) // Inc - Условие наличия компонента. .Inc() @@ -501,42 +574,47 @@ EcsMask mask = _staticMask.ToMask(_world); ## Аспект -Пользовательские классы наследуемые от `EcsAspect` и используемые для взаимодействия с сущностями. Аспекты одновременно являются кешем пулов и содержат маску. Можно рассматривать аспекты как описание того с какими сущностями работает система. -Упрощенный синтаксис: +Пользовательские классы наследуемые от `EcsAspect`, описывающие наборы компонентов, с которыми работает система. Аспект одновременно выполняет две функции: ++ Маска — инициализирует и хранит [маску](#Маска), за счет чего может использоваться в запросах. ++ Кэш пулов — предоставляет быстрый доступ к пулам компонентов. + + +Проще говоря, аспект — это удобный способ описать "с какими сущностями я работаю и как получать их компоненты". + + +Пример: ``` c# -using DCFApixels.DragonECS; -// ... class Aspect : EcsAspect { - // Кешируется пул и Pose добавляется во включающее ограничение. + // Кешируется пул и тип Pose добавляется во включающее условие. public EcsPool poses = Inc; - // Кешируется пул и Velocity добавляется во включающее ограничение. + // Кешируется пул и тип Velocity добавляется во включающее условие. public EcsPool velocities = Inc; - // Кешируется пул и FreezedTag добавляется в исключающее ограничение. + // Кешируется пул и тип FreezedTag добавляется в исключающее условие. public EcsTagPool freezedTags = Exc; - - // При запросах будет проверяться наличие компонентов - // из включающего ограничения маски и отсутствие из исключающего. - // Так же есть Opt - только кеширует пул, не влияя на маску. } ``` +Назначение статических свойств: ++ Inc — компонент должен быть у сущности (включающее условие) + кеширует пул ++ Exc — компонента не должно быть у сущности (исключающее условие) + кеширует пул ++ Opt — компонент может быть, но не влияет на фильтрацию (только кеширует пул для доступа) ++ Any — хотя бы один из компонентов с Any должен присутствовать + кеширует пул +
-Явный синтаксис (результат идентичен примеру выше): +Инициализация через метод (результат идентичен примеру выше): ``` c# -using DCFApixels.DragonECS; -// ... class Aspect : EcsAspect { public EcsPool poses; public EcsPool velocities; protected override void Init(Builder b) { - poses = b.Include(); - velocities = b.Include(); - b.Exclude(); + poses = b.IncludePool(); + velocities = b.IncludePool(); + b.ExcludePool(); } } ``` @@ -546,10 +624,8 @@ class Aspect : EcsAspect
Комбинирование аспектов -В аспекты можно добавлять другие аспекты, тем самым комбинируя их. Ограничения так же будут скомбинированы. +В аспекты можно добавлять другие аспекты, тем самым комбинируя их. Маски так же будут скомбинированы. ``` c# -using DCFApixels.DragonECS; -// ... class Aspect : EcsAspect { public OtherAspect1 otherAspect1; @@ -562,7 +638,7 @@ class Aspect : EcsAspect otherAspect1 = b.Combine(1); // Хотя для OtherAspect1 метод Combine был вызван раньше, сначала будет скомбинирован с OtherAspect2, так как по умолчанию order = 0. otherAspect2 = b.Combine(); - // Если в OtherAspect1 или в OtherAspect2 было ограничение b.Exclude() тут оно будет заменено на b.Include(). + // Если в OtherAspect1 или в OtherAspect2 было условие b.Exclude() тут оно будет заменено на b.Include(). poses = b.Include(); } } @@ -578,11 +654,11 @@ class Aspect : EcsAspect
## Запросы -Фильтруют сущности и выдают коллекции сущностей удовлетворяющие определенным условиям. Встроенный запрос `Where` фильтрует на соответствие условиям маски компонентов и имеет несколько перегрузок: +Запросы позволяют отфильтровать и получать коллекции сущностей, удовлетворяющих заданным условиям. Основной метод — `Where`, который фильтрует по маске компонентов и имеет несколько перегрузок: ++ `EcsWorld.Where(out TAspect aspect)` - Фильтрация по маске, определённой в аспекте, плюс получение самого аспекта с закешированными пулами. + `EcsWorld.Where(EcsMask mask)` - Обычная фильтрация по маске; -+ `EcsWorld.Where(out TAspect aspect)` - Сочетает в себе фильтрацию по маске из аспекта и получение аспекта; -Запрос `Where` применим как к `EcsWorld` так и коллекциям фреймворка (в этом плане Where чем-то похож на аналогичный из Linq). Так же имеются перегрузки для сортировки сущностей по `Comparison`. +`Where` можно вызывать не только у мира, но и у любых коллекций фреймворка (в этом плане Where чем-то похож на аналогичный из Linq). Также доступны перегрузки для сортировки сущностей с помощью `Comparison`. Пример системы: ``` c# @@ -597,10 +673,9 @@ public class SomeDamageSystem : IEcsRun, IEcsInject public EcsTagPool isDiedSignals = Opt; } EcsDefaultWorld _world; - public void Inject(EcsDefaultWorld world) => _world = world; - public void Run() { + // Запрашиваем сущности удовлетворяющее маске из Aspect foreach (var e in _world.Where(out Aspect a)) { // Сюда попадают сущности с компонентами Health, DamageSignal и без IsInvulnerable. @@ -615,6 +690,7 @@ public class SomeDamageSystem : IEcsRun, IEcsInject } } } + public void Inject(EcsDefaultWorld world) => _world = world; } ``` @@ -623,7 +699,7 @@ public class SomeDamageSystem : IEcsRun, IEcsInject ## Коллекции ### EcsSpan -Коллекция сущностей, доступная только для чтения и выделяемая только в стеке. Состоит из ссылки на массив, длинны и идентификатора мира. Аналог `ReadOnlySpan`. +`ref struct` коллекция сущностей, доступная только для чтения. Состоит из ссылки на массив, длинны и идентификатора мира. Аналог `ReadOnlySpan`. ``` c# // Запрос Where возвращает сущности в виде EcsSpan. EcsSpan es = _world.Where(out Aspect a); @@ -641,7 +717,7 @@ for (int i = 0; i < es.Count; i++) > Хотя `EcsSpan` является просто массивом, в нем не допускается дублирование сущностей. ### EcsGroup -Вспомогательная коллекция основанная на Sparse Set для хранения множества сущностей с O(1) операциями добавления/удаления/проверки и т.д. +Вспомогательная коллекция основанная на Sparse Set для хранения множества сущностей с `O(1)` операциями добавления/удаления/проверки и т.д. ``` c# // Получаем новую группу. EcsWorld содержит в себе пул групп, // поэтому будет переиспользована свободная или создана новая. @@ -1011,6 +1087,23 @@ public struct WorldComponent : IEcsWorldComponent ## Опубликованные проекты: + + + + + + +
+ + Crystal Siege + + + + + Order matters + + +
@@ -1019,33 +1112,17 @@ public struct WorldComponent : IEcsWorldComponent - - ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ + _____________ screenshot -

-# Расширения -* Пакеты: - * [Интеграция с движком 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) - * [Графы](https://github.com/DCFApixels/DragonECS-Graphs) -* Утилиты: - * [Упрощенный синтаксис](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.х в консоли может выпадать ошибка: ``` diff --git a/README-ZH.md b/README-ZH.md index 7266641..6e6777c 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -19,7 +19,7 @@ - +
Русский
@@ -31,7 +31,7 @@ - +
中文
diff --git a/README.md b/README.md index 8edb090..c3f9193 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ - +
Русский
@@ -33,7 +33,7 @@ - +
中文
From 859ea67511718ae66ced8b9ccf385a16145f09bb Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:44:57 +0800 Subject: [PATCH 6/6] up version to 0.9.21 --- DragonECS.csproj | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DragonECS.csproj b/DragonECS.csproj index 44dcf4f..3fdfabc 100644 --- a/DragonECS.csproj +++ b/DragonECS.csproj @@ -10,7 +10,7 @@ DCFApixels.DragonECS DragonECS - 0.9.20 + 0.9.21 DCFApixels ECS Framework for Game Engines with C# and .Net Platform DCFApixels diff --git a/package.json b/package.json index e596002..53672b0 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "displayName": "DragonECS", "description": "C# Entity Component System Framework", "unity": "2020.3", - "version": "0.9.20", + "version": "0.9.21", "repository": { "type": "git", "url": "https://github.com/DCFApixels/DragonECS.git"