From 9aa4d21e799ca2763ef0fd7feecd7c6057753220 Mon Sep 17 00:00:00 2001
From: Mikhail <99481254+DCFApixels@users.noreply.github.com>
Date: Mon, 2 Mar 2026 17:01:46 +0800
Subject: [PATCH] remove IEntityTemplate / update readme
---
README-RU.md | 86 +++++++++----------
src/Connectors/EcsEntityConnect.cs | 4 +-
src/Connectors/GameObjectConnect.cs | 6 ++
.../Editor/ComponentTemplatePropertyDrawer.cs | 1 -
.../Editor/EntityTemplateEditor.cs | 23 +----
.../EntityTemplate/IEntityTemplate.cs | 26 ------
.../EntityTemplate/IEntityTemplate.cs.meta | 11 ---
.../Templates/MonoEntityTemplate.cs | 11 +--
.../Templates/ScriptableEntityTemplate.cs | 11 +--
9 files changed, 57 insertions(+), 122 deletions(-)
delete mode 100644 src/Templates/EntityTemplate/IEntityTemplate.cs
delete mode 100644 src/Templates/EntityTemplate/IEntityTemplate.cs.meta
diff --git a/README-RU.md b/README-RU.md
index 0eeb088..1131b04 100644
--- a/README-RU.md
+++ b/README-RU.md
@@ -48,10 +48,10 @@
# Оглавление
- [Установка](#установка)
- [Debug](#debug)
- - [Debug Модуль](#debug-модуль)
- [Debug Сервис](#debug-сервис)
+ - [Debug Модуль](#debug-модуль)
- [Визуальная отладка](#визуальная-отладка)
-- [Шаблон Сущности](#шаблон-сущности)
+- [Шаблоны](#шаблоны)
- [Связь с GameObject](#связь-с-gameobject)
- [World Provider](#world-provider)
- [Шаблон Пайплайна](#шаблон-пайплайна)
@@ -85,21 +85,8 @@ https://github.com/DCFApixels/DragonECS-Unity.git
# Debug
-## Debug Модуль
-Подключение модуля отладки в Unity.
-```c#
-EcsDefaultWorld _world = new EcsDefaultWorld();
-EcsEventWorld _eventWorld = new EcsDefaultWorld();
-
-_pipeline = EcsPipeline.New()
- //...
- // Подключение и инициализация отладки для миров _world и _eventWorld
- .AddUnityDebug(_world, _eventWorld)
- //...
- .BuildAndInit();
-```
## Debug Сервис
-`UnityDebugService`- реализация [Debug-сервиса для `EcsDebug`](https://github.com/DCFApixels/DragonECS/blob/main/README-RU.md#ecsdebug). В редакторе по умолчанию автоматически инициализируется и связывает `EcsDebug.Print` с консолью Unity, `EcsProfilerMarker` c профайлером и т.д.
+`UnityDebugService` - реализация [Debug-сервиса для `EcsDebug`](https://github.com/DCFApixels/DragonECS/blob/main/README-RU.md#ecsdebug). В редакторе он инициализируется автоматически и обеспечивает интеграцию: например, вызовы `EcsDebug.Print` направляются в консоль Unity, а `EcsProfilerMarker` подключается к встроенному профайлеру и т.д.
```c#
//Ручная активация.
UnityDebugService.Activate();
@@ -115,8 +102,19 @@ someMarker.End();
//Остановка игрового режима.
EcsDebug.Break();
```
+
## Визуальная отладка
-Выполнена в виде специальных объектов-мониторов в которых отображается состояние разных аспектов фреймворка. Найти эти мониторы можно в Play Mode в разделе `DontDestroyOnLoad`.
+
+Выполнена в виде специальных объектов-мониторов в которых отображается состояние разных частей фреймворка. Найти эти мониторы можно в `Play Mode` в разделе `DontDestroyOnLoad`.
+
+```c#
+_pipeline = EcsPipeline.New()
+ //...
+ // Инициализация отладки для пайплайна и миров
+ .AddUnityDebug(_world, _eventWorld)
+ //...
+ .BuildAndInit();
+```
@@ -143,7 +141,7 @@ EcsDebug.Break();
-----
* ### `WorldMonitor`
-Показывает состояние `EcsWorld`. на каждый казанный мир создается отдельный монитор.
+Показывает состояние `EcsWorld`. на каждый мир, переданный в `AddUnityDebug(...)`, создается отдельный монитор.
@@ -162,26 +160,11 @@ EcsDebug.Break();
-# Шаблон Сущности
-Настраиваемый набор компонентов которые можно применить к сущностям. Шаблоны должны реализовывать интерфейс `ITemplateNode`.
-```c#
-ITemplateNode someTemplate = /*...*/;
-//...
-foreach (var e in _world.Where(out Aspect a))
-{
- // Применение шаблона сущности.
- someTemplate.Apply(e, _world.id);
-}
-```
-```c#
-// Применение шаблона сразу при создании сущности.
-int e = _world.NewEntity(someTemplate);
-```
-По умолчанию расширение содержит 2 вида шаблонов: `ScriptableEntityTemplate`, `MonoEntityTemplate`.
+# Шаблоны
+Интеграция содержит шаблоны расширяющие `ITemplateNode`, предназначенные для настройки сущностей из редактора.
## ScriptableEntityTemplate
Хранится как отдельный ассет. Наследуется от `ScriptableObject`.
-Действия чтобы создать `ScriptableEntityTemplate` ассет:
Создать ассет: Asset > Create > DragonECS > ScriptableEntityTemplate.
@@ -222,8 +205,9 @@ int e = _world.NewEntity(someTemplate);
## Шаблон компонента
+Чтобы компонент попал в меню `Add Component` требуется шаблон. Шаблоны компонента это типы реализующие `IComponentTemplate`.
+
### Реализация
-Чтобы компонент попал в меню `Add Component` нужно реализовать шаблон компонента. Шаблоны компонента это типы реализующие `IComponentTemplate`.
* Упрощенная реализация:
```c#
@@ -243,6 +227,8 @@ class SomeTagComponentTemplate : TagComponentTemplate { }
* Полная реализация:
+Если не подходят `ComponentTemplate` или `TagComponentTemplate`, можно напрямую реализовать интерфейс `IComponentTemplate`. Например это может пригодиться для работы в связке с кастомной реализацией пула. В большинстве случаев достаточно упрощенной.
+
```c#
[Serializable]
struct SomeComponent : IEcsComponent { /* ... */ }
@@ -251,6 +237,7 @@ class SomeComponentTemplate : IComponentTemplate
[SerializeField]
protected SomeComponent component;
public Type Type { get { return typeof(SomeComponent); } }
+ public bool IsUnique { get { return true; } }
public void Apply(int worldID, int entityID)
{
EcsWorld.GetPoolInstance>(worldID).TryAddOrGet(entityID) = component;
@@ -268,28 +255,37 @@ class SomeComponentTemplate : IComponentTemplate
### Кастомизация отображения типов
В раскрывающемся при нажатии `Add Component` меню выбора компонента поддерживается иерархическое группирование. Производится группирование на основе мета-атрибута `[MetaGroup]`.
-Компоненты в инспекторе по умолчанию отображаются окрашенными в случайный цвет сгенерированный на основе имени компонента, выбрать другой режим окраски можно в [окне настроек](#окно-настроек) фреймворка. Задать конкретный цвет можно при помощи мета-атрибута `[MetaColor]`.
+Компоненты в инспекторе по умолчанию отображаются со случайным цветом, зависящим от его имени, выбрать другой режим окраски можно в [окне настроек](#окно-настроек) фреймворка. Задать конкретный цвет можно при помощи мета-атрибута `[MetaColor]`.
-Если редактор смог автоматически определить связанный с компонентом скрипт, то слева от крестика удаления компонента будет иконка файла. Клик по иконке выделит файл скрипта в папке проекта, двойной клик откроет скрип для редактирования. Связанный файл ищется по сопоставлению имени типа и имени файла скрипта.
+Если интеграции удается найти соответствующий скрипт (по совпадению имени типа и файла, либо при наличии `[MetaID]`), рядом с крестиком удаления появляется иконка файла — клик выделяет скрипт в проекте, двойной клик открывает его.
-Если у компонента есть мета-атрибут `[MetaDescription]`, то слева от крестика удаления компонента будет иконка подсказки, при наведении курсора покажется информация из `[MetaDescription]`.
+При наличии атрибута `[MetaDescription]` показывается иконка подсказки с текстом из него.
### Применение шаблонов компонентов вне стандартных шаблонов сущностей
-При необходимости создания пользовательского шаблона, шаблоны компонентов поддерживают отображение вне стандартных `MonoEntityTemplate` и `ScriptableEntityTemplate`.
+Шаблоны компонентов можно использовать не только внутри стандартных `MonoEntityTemplate` и `ScriptableEntityTemplate`, но и в любых пользовательских классах. Для этого предусмотрены два способа:
+
+Атрибут `[ComponentTemplateReference]`:
```c#
-// ComponentTemplateReference добавляет кнопку выбора доступной реализации IComponentTemplate
+// Добавляет кнопку выбора доступной реализации IComponentTemplate
// и отображает шаблон компонента аналогично компонентам в MonoEntityTemplate или ScriptableEntityTemplate.
[SerializeReference, ComponentTemplateReference]
-private IComponentTempalte _someComponent1;
+private IComponentTemplate _someComponent1;
+```
-// Обертка над IComponentTempalte, которая работает аналогично примеру с атрибутом ComponentTemplateReference.
+Обертка `ComponentTemplateProperty`:
+```c#
+// Обертка над IComponentTemplate, аналогично примеру с атрибутом ComponentTemplateReference.
private ComponentTemplateProperty _someComponent2;
+```
-// Все это работает и для массивов.
+Оба подхода работают и для массивов:
+```c#
[SerializeReference, ComponentTemplateReference]
-private IComponentTempalte[] _components;
+private IComponentTemplate[] _components;
+// или
+private ComponentTemplateProperty[] _components;
```
diff --git a/src/Connectors/EcsEntityConnect.cs b/src/Connectors/EcsEntityConnect.cs
index cb9e103..8a53fb6 100644
--- a/src/Connectors/EcsEntityConnect.cs
+++ b/src/Connectors/EcsEntityConnect.cs
@@ -113,9 +113,9 @@ namespace DCFApixels.DragonECS
{
get { return _monoTemplates; }
}
- public IEnumerable AllTemplates
+ public IEnumerable AllTemplates
{
- get { return ((IEnumerable)_scriptableTemplates).Concat(_monoTemplates); }
+ get { return ((IEnumerable)_scriptableTemplates).Concat(_monoTemplates); }
}
#endregion
diff --git a/src/Connectors/GameObjectConnect.cs b/src/Connectors/GameObjectConnect.cs
index b5ebdde..dd30270 100644
--- a/src/Connectors/GameObjectConnect.cs
+++ b/src/Connectors/GameObjectConnect.cs
@@ -84,6 +84,12 @@ namespace DCFApixels.DragonECS
public static class GameObjectRefExt
{
+ public static entlong NewEntityWithGameObject(this EcsWorld world, ITemplateNode template, string name = "Entity", GameObjectIcon icon = GameObjectIcon.NONE)
+ {
+ entlong e = world.NewEntityWithGameObject(name, icon);
+ template.Apply(world.ID, e.ID);
+ return e;
+ }
public static entlong NewEntityWithGameObject(this EcsWorld self, string name = "Entity", GameObjectIcon icon = GameObjectIcon.NONE)
{
entlong result = self.NewEntityLong();
diff --git a/src/Templates/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs b/src/Templates/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs
index f87d874..8591dd0 100644
--- a/src/Templates/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs
+++ b/src/Templates/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs
@@ -33,7 +33,6 @@ namespace DCFApixels.DragonECS.Unity.Editors
private static ComponentTemplatesDropDown _componentDropDown;
#region Properties
- private float SingleLineWithPadding => OneLineHeight + Padding * 4f;
private float Padding => Spacing;
protected override bool IsStaticInit => _componentDropDown != null;
#endregion
diff --git a/src/Templates/EntityTemplate/Editor/EntityTemplateEditor.cs b/src/Templates/EntityTemplate/Editor/EntityTemplateEditor.cs
index 5585279..4c74f71 100644
--- a/src/Templates/EntityTemplate/Editor/EntityTemplateEditor.cs
+++ b/src/Templates/EntityTemplate/Editor/EntityTemplateEditor.cs
@@ -7,7 +7,7 @@ using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors
{
- internal abstract class EntityTemplateEditorBase : ExtendedEditor
+ internal abstract class EntityTemplateEditorBase : ExtendedEditor
{
private ComponentTemplatesDropDown _componentDropDown;
@@ -17,15 +17,13 @@ namespace DCFApixels.DragonECS.Unity.Editors
protected abstract bool IsSO { get; }
- //public virtual bool IsStaticData { get { return false; } }
-
#region Init
protected override bool IsInit { get { return _componentDropDown != null; } }
protected override void OnInit()
{
_componentDropDown = new ComponentTemplatesDropDown();
- _componentsProp = serializedObject.FindProperty(Target.ComponentsPropertyName);
+ _componentsProp = serializedObject.FindProperty("_componentTemplates");
_reorderableComponentsList = new ReorderableList(serializedObject, _componentsProp, true, false, false, false);
_reorderableComponentsList.onAddCallback += OnReorderableComponentsListAdd;
@@ -142,19 +140,6 @@ namespace DCFApixels.DragonECS.Unity.Editors
#endregion
- #region Add/Remove
- private void OnRemoveComponentAt(int index)
- {
- if (this.target is IEntityTemplateInternal target)
- {
- SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
- componentsProp.DeleteArrayElementAtIndex(index);
- serializedObject.ApplyModifiedProperties();
- EditorUtility.SetDirty(this.target);
- }
- }
- #endregion
-
protected override void DrawCustom()
{
Init();
@@ -204,7 +189,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
{
using (EcsGUI.Layout.BeginVertical(UnityEditorUtility.GetTransperentBlackBackgrounStyle()))
{
- DrawTop(Target, _componentsProp);
+ DrawTop(_componentsProp);
_reorderableComponentsList.DoLayoutList();
}
}
@@ -214,7 +199,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
}
}
- private void DrawTop(IEntityTemplateInternal target, SerializedProperty componentsProp)
+ private void DrawTop(SerializedProperty componentsProp)
{
GUILayout.Space(2f);
diff --git a/src/Templates/EntityTemplate/IEntityTemplate.cs b/src/Templates/EntityTemplate/IEntityTemplate.cs
deleted file mode 100644
index 552de85..0000000
--- a/src/Templates/EntityTemplate/IEntityTemplate.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-#if DISABLE_DEBUG
-#undef DEBUG
-#endif
-
-namespace DCFApixels.DragonECS
-{
- public interface IEntityTemplate : ITemplateNode { }
-
- public static class ITemplateNodeExtensions
- {
- public static entlong NewEntityWithGameObject(this EcsWorld world, ITemplateNode template, string name = "Entity", GameObjectIcon icon = GameObjectIcon.NONE)
- {
- entlong e = world.NewEntityWithGameObject(name, icon);
- template.Apply(world.ID, e.ID);
- return e;
- }
- }
-}
-
-namespace DCFApixels.DragonECS.Unity.Internal
-{
- internal interface IEntityTemplateInternal : IEntityTemplate
- {
- string ComponentsPropertyName { get; }
- }
-}
\ No newline at end of file
diff --git a/src/Templates/EntityTemplate/IEntityTemplate.cs.meta b/src/Templates/EntityTemplate/IEntityTemplate.cs.meta
deleted file mode 100644
index c3e7e3c..0000000
--- a/src/Templates/EntityTemplate/IEntityTemplate.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 33a7d50d86178eb43a36d5e8bdd70982
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/src/Templates/EntityTemplate/Templates/MonoEntityTemplate.cs b/src/Templates/EntityTemplate/Templates/MonoEntityTemplate.cs
index 21d8915..08cb1d7 100644
--- a/src/Templates/EntityTemplate/Templates/MonoEntityTemplate.cs
+++ b/src/Templates/EntityTemplate/Templates/MonoEntityTemplate.cs
@@ -11,7 +11,7 @@ using UnityEngine.Serialization;
namespace DCFApixels.DragonECS
{
- public abstract class MonoEntityTemplateBase : MonoBehaviour, IEntityTemplate
+ public abstract class MonoEntityTemplateBase : MonoBehaviour, ITemplateNode
{
public abstract void Apply(short worldID, int entityID);
}
@@ -22,20 +22,13 @@ namespace DCFApixels.DragonECS
[MetaGroup(EcsUnityConsts.PACK_GROUP, EcsUnityConsts.ENTITY_BUILDING_GROUP)]
[MetaDescription(EcsConsts.AUTHOR, nameof(MonoBehaviour) + " implementation of an entity template. Templates are a set of components that are applied to entities.")]
[MetaID("DragonECS_C734BA8092014833C14F21E05D7B1551")]
- public class MonoEntityTemplate : MonoEntityTemplateBase, IEntityTemplateInternal
+ public class MonoEntityTemplate : MonoEntityTemplateBase, ITemplateNode
{
[SerializeReference]
[ReferenceButton(true, typeof(IComponentTemplate))]
[FormerlySerializedAs("_components")]
private IComponentTemplate[] _componentTemplates;
- #region Properties
- string IEntityTemplateInternal.ComponentsPropertyName
- {
- get { return nameof(_componentTemplates); }
- }
- #endregion
-
#region Methods
public ReadOnlySpan GetComponentTemplates()
{
diff --git a/src/Templates/EntityTemplate/Templates/ScriptableEntityTemplate.cs b/src/Templates/EntityTemplate/Templates/ScriptableEntityTemplate.cs
index 07e92ae..675acd1 100644
--- a/src/Templates/EntityTemplate/Templates/ScriptableEntityTemplate.cs
+++ b/src/Templates/EntityTemplate/Templates/ScriptableEntityTemplate.cs
@@ -11,7 +11,7 @@ using UnityEngine.Serialization;
namespace DCFApixels.DragonECS
{
- public abstract class ScriptableEntityTemplateBase : ScriptableObject, IEntityTemplate
+ public abstract class ScriptableEntityTemplateBase : ScriptableObject, ITemplateNode
{
public abstract void Apply(short worldID, int entityID);
}
@@ -21,7 +21,7 @@ namespace DCFApixels.DragonECS
[MetaDescription(EcsConsts.AUTHOR, nameof(ScriptableObject) + " implementation of an entity template. Templates are a set of components that are applied to entities.")]
[CreateAssetMenu(fileName = nameof(ScriptableEntityTemplate), menuName = EcsConsts.FRAMEWORK_NAME + "/" + nameof(ScriptableEntityTemplate), order = 1)]
[MetaID("DragonECS_7C4DBA809201D959401A5BDFB6363EC0")]
- public class ScriptableEntityTemplate : ScriptableEntityTemplateBase, IEntityTemplateInternal
+ public class ScriptableEntityTemplate : ScriptableEntityTemplateBase, ITemplateNode
{
[SerializeField]
private ScriptableEntityTemplateBase[] _templates;
@@ -30,13 +30,6 @@ namespace DCFApixels.DragonECS
[FormerlySerializedAs("_components")]
private IComponentTemplate[] _componentTemplates;
- #region Properties
- string IEntityTemplateInternal.ComponentsPropertyName
- {
- get { return nameof(_componentTemplates); }
- }
- #endregion
-
#region Methods
public ReadOnlySpan GetTemplates()
{