diff --git a/README-RU.md b/README-RU.md index b848617..95a4080 100644 --- a/README-RU.md +++ b/README-RU.md @@ -58,6 +58,7 @@ - [FixedUpdate LateUpdate](#fixedupdate-lateupdate) - [Документация проекта](#документация-проекта) - [Окно настроек](#окно-настроек) +- [Reference Repairer](#Reference-Repairer) - [FAQ](#faq)
@@ -70,9 +71,6 @@ + Минимальная версия C# 8.0; + Минимальная версия Unity 2021.2.0; -Протестировано на: -* **Unity:** Минимальная версия 2021.2.0. - ## Установка для Unity * ### Unity-модуль Поддерживается установка в виде Unity-модуля при помощи добавления git-URL [в PackageManager](https://docs.unity3d.com/2023.2/Documentation/Manual/upm-ui-giturl.html): @@ -210,7 +208,7 @@ _pipeline = EcsPipeline.New() ## Шаблон компонента -Чтобы компонент попал в меню `Add Component` требуется шаблон. Шаблоны компонента это типы реализующие `IComponentTemplate` или `ITemplateNode` вместе с `IEcsComponentMember`. +Чтобы компонент попал в меню `Add Component` требуется шаблон. Шаблоны компонента это типы реализующие `IComponentTemplate` или компоненты реализующие `ITemplateNode` вместе с `IEcsComponentMember`. ### Реализация @@ -516,8 +514,8 @@ public class EcsRoot : MonoBehaviour
-# Инструмент для восстановления Missing Reference -Некоторые части интеграции активно задействует `[SerializeReference]`, у которого есть известная проблема с потерей типов при переименовании. Чтобы упростить восстановление потерянных типов имеется специальный инструмент `Reference Repairer`. Он может собирать все ассеты с потерянными типами, после этого предоставляет окно для указания новых имён потерянных типов и выполнит их восстановление в собранных ассетах. Открыть окно инструмента: `Tools > DragonECS > Reference Repairer`. +# Reference Repairer +Инструмент для восстановления Missing Reference. Некоторые части интеграции активно задействует `[SerializeReference]`, у которого есть известная проблема с потерей типов при переименовании. `Reference Repairer` упрощает процесс восстановления. Он может собирать все ассеты с потерянными типами, после этого предоставляет окно для указания новых имён потерянных типов и выполнит их восстановление в собранных ассетах. Открыть окно инструмента: `Tools > DragonECS > Reference Repairer`. > Если потерянные типы имеют атрибут `[MetaID(id)]`, инструмент попытается автоматически сопоставить новое имя типа.

diff --git a/README.md b/README.md index 164c5d2..511740a 100644 --- a/README.md +++ b/README.md @@ -35,33 +35,494 @@
-The extension will add a set of tools for debugging and communicating with the Unity engine. +This package integrates DragonECS with the Unity editor and runtime. It provides visual debugging and profiling tools, editor templates for entity/component setup, and utilities for binding entities to Unity GameObjects. > [!WARNING] > The project is a work in progress, API may change. > -> While the English version of the README is incomplete, you can view the [Russian version](https://github.com/DCFApixels/DragonECS-Unity/blob/main/README-RU.md). +> While the English version of the README is incomplete, the [Russian README](https://github.com/DCFApixels/DragonECS-Unity/blob/main/README-RU.md) contains additional details. + +//https://gist.github.com/DCFApixels/c250f2561f09e09ab3e6a4bd4f3013cb#file-unitycomponenttemplates-cs + +# Table of contents +- [Installation](#installation) +- [Debug](#debug) + - [Debug service](#debug-service) + - [Debug module](#debug-module) + - [Visual debugging](#Visual-debugging) +- [Templates](#Templates) +- [Binding to GameObjects](#Binding-to-GameObjects) +- [World Provider](#world-provider) +- [Pipeline template](#Pipeline-template) +- [FixedUpdate LateUpdate](#fixedupdate-lateupdate) +- [Project documentation](#Project-documentation) +- [Settings window](#Settings-window) +- [Reference Repairer](#Reference-Repairer) +- [FAQ](#faq)
# Installation -Versioning semantics - [Open](https://gist.github.com/DCFApixels/e53281d4628b19fe5278f3e77a7da9e8#file-dcfapixels_versioning_ru-md) +Versioning semantics - [Open](https://gist.github.com/DCFApixels/af79284955bf40e9476cdcac79d7b098#file-dcfapixels_versioning-md) + ## Environment Requirements: -+ Dependency: [DragonECS](https://github.com/DCFApixels/DragonECS) -+ Minimum version of C# 8.0; -+ Minimum version of Unity 2021.2.0; - -Tested with: -+ **Unity:** Minimum version 2021.2.0; +- Dependency: [DragonECS](https://github.com/DCFApixels/DragonECS) +- Minimum C# version: 8.0 +- Minimum Unity version: 2021.2.0 ## Unity Installation -* ### Unity Package -The package can be installed as a Unity package by adding the Git URL [in the PackageManager](https://docs.unity3d.com/2023.2/Documentation/Manual/upm-ui-giturl.html) or manually adding it to `Packages/manifest.json`: +* ### Unity package +Installation as a Unity package is supported by adding the Git URL [in PackageManager](https://docs.unity3d.com/2023.2/Documentation/Manual/upm-ui-giturl.html): ``` https://github.com/DCFApixels/DragonECS-Unity.git ``` -* ### Source Code -The package can also be added to the project as source code. +Or add the package entry to `Packages/manifest.json`: +``` +"com.dcfa_pixels.dragonecs-unity": "https://github.com/DCFApixels/DragonECS-Unity.git", +``` + +### Source install +The package sources can be copied directly into the project.
+ +# Debug +## Debug service +`UnityDebugService` implementation of the [Debug service for `EcsDebug`](https://github.com/DCFApixels/DragonECS/blob/main/README.md#ecsdebug). In the editor it initializes automatically and integrates with Unity systems: `EcsDebug.Print` is forwarded to the Unity console, `EcsProfilerMarker` is connected to the Unity profiler, and related debug functionality is exposed. +```c# +// Activate manually +UnityDebugService.Activate(); + +// Print to Unity console +EcsDebug.Print("Example message"); + +var someMarker = new EcsProfilerMarker("SomeMarker"); +someMarker.Begin(); +// Measured time will be visible in the Unity profiler. +someMarker.End(); + +// Stop play mode +EcsDebug.Break(); +``` + +## Visual debugging + +Visual debugging is provided as editor monitor objects that display internal framework state during `Play Mode`. Monitors are placed in the `DontDestroyOnLoad` section. + +```c# +_pipeline = EcsPipeline.New() + //... + // Debugging initialization for the pipeline and worlds. + .AddUnityDebug(_world, _eventWorld) + //... + .BuildAndInit(); +``` + +

+ +

+ +----- + +* ### `PipelineMonitor` +Displays `EcsPipeline` state. Systems are displayed in the order of their execution. + +

+ +

+ +----- + +* ### `PipelineProcessMonitor` +Displays processes and systems in a matrix layout. Systems are shown in execution order. A mark at the intersection of a system and a process indicates that the system is part of that process. + +

+ +

+ +----- + +* ### `WorldMonitor` +Displays `EcsWorld` state. A separate monitor is created for each world passed to `AddUnityDebug(...)`. + +

+ +

+ +----- + +* ### `EntityMonitor` +Displays entity state and allows adding, modifying or removing components at runtime (Play Mode). One monitor is created per entity; entity monitors are grouped under the corresponding world monitor. + +

+ +

+ +----- + +
+ +# Templates +The integration provides templates that extend `ITemplateNode` for editor-driven entity configuration. + +## ScriptableEntityTemplate +Stored as a `ScriptableObject` asset. + +
+Create asset: Asset > Create > DragonECS > ScriptableEntityTemplate. + +

+ +

+ +
+ +To add a component to the `Add Component` menu, a [component template](#component-template) is required. + +

+ +

+ +----- + +## MonoEntityTemplate +Attachable to a `GameObject`. Inherits from `MonoBehaviour`. + +
+Add component: Add Component > DragonECS > MonoEntityTemplate. + +

+ +

+ +
+ +To add a component to the `Add Component` menu, a [component template](#component-template) is required. + +

+ +

+ +----- + +## Component Template + +To expose a component in the `Add Component` menu, a template is required. Component templates are types implementing `IComponentTemplate` or components implementing `ITemplateNode` together with `IEcsComponentMember`. + +### Implementation + +* Simple example: +```c# +// Add [Serializable] attribute to the component type. +[Serializable] +struct SomeComponent : IEcsComponent { /* ... */ } +class SomeComponentTemplate : ComponentTemplate { } +``` + +```c# +// Same for tag components. +[Serializable] +struct SomeTagComponent : IEcsTagComponent { } +class SomeTagComponentTemplate : TagComponentTemplate { } +``` + +
+Other approaches + +#### Implementing `ITemplateNode` on a component + +This approach can be convenient because it does not require a separate template class; the component itself acts as the template and is straightforward to implement. The downside is higher risk of missing references when types are renamed if `[SerializeReference]` is used. +```c# +public struct Health : IEcsComponent, ITemplateNode +{ + public float Points; + public void Apply(short worldID, int entityID) + { + EcsPool.Apply(worldID, entityID) = this; + } +} +``` + +#### Custom template implementation + +If built-in `ComponentTemplate` or `TagComponentTemplate` do not fit the requirements, implement a custom template by implementing `IComponentTemplate`. This can be useful for custom pools. In most cases the built-in templates are sufficient. + +```c# +[Serializable] +struct SomeComponent : IEcsComponent { /* ... */ } +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) + { + EcsPool.Apply(worldID, entityID) = component; + } + public object GetRaw() { return component; } + public void SetRaw(object raw) { component = (SomeComponent)raw; } + public void OnGizmos(Transform transform, IComponentTemplate.GizmosMode mode) { /*...*/ } + public void OnValidate(UnityEngine.Object obj) { /*...*/ } +} +``` + +
+
+ +### Customizing type display +The `Add Component` dropdown supports hierarchical grouping based on the `[MetaGroup]` attribute. + +By default components in the Inspector receive a deterministic color derived from the component name. The display mode can be changed in the settings window. A specific color can be set using the `[MetaColor]` attribute. + +If the integration locates the corresponding script (by matching the type name to a file or via `[MetaID]`), a file icon appears next to the remove button — single-click selects the script in the project, double-click opens it. + +If `[MetaDescription]` is present, a tooltip icon is shown with the description text. + +
+ +### Using component templates outside standard entity templates +Component templates can be used outside of `MonoEntityTemplate` and `ScriptableEntityTemplate` in arbitrary classes. Two approaches are provided: + +Attribute `[ComponentTemplateField]`: +```c# +// Display a field as a component, customizable with meta attributes. +// Similar to components in MonoEntityTemplate or ScriptableEntityTemplate. +[SerializeField, ComponentTemplateField] +private SomeComponent _someComponent1; +``` +```c# +// For SerializeReference adds a button to pick available ITemplateNode implementation +[SerializeReference, ComponentTemplateField] +private ITemplateNode _someComponent1; +``` + +Wrapper `ComponentTemplateProperty`: +```c# +// Wrapper around ITemplateNode, similar to the ComponentTemplateField example. +private ComponentTemplateProperty _someComponent2; +``` + +Both approaches work for arrays too: +```c# +[SerializeReference, ComponentTemplateField] +private IComponentTemplate[] _components; +// or +private ComponentTemplateProperty[] _components; +``` + +
+ +# Binding to GameObjects +Entities and GameObjects are linked using connects. From the GameObject side use `EcsEntityConnect`; from the entity side `GameObjectConnect` is created/removed automatically. `EcsEntityConnect` acts as the manager connect. +```c# +EcsEntityConnect connect = /*...*/; +entlong entity = _world.NewEntityLong(); + +// Connect entity with GameObject. +// GameObjectConnect is added to the entity automatically +// and templates are applied. +connect.ConnectWith(entity); + +// Or create without applying templates. +connect.ConnectWith(entity, false); + +// Disconnect. +// GameObjectConnect will be removed automatically. +connect.Disconnect(); +``` +
+Add component: Add Component > DragonECS > EcsEntityConnect. + +

+ +

+ +
+ +

+ +

+ +> To view all components of the linked entity, expand `RUNTIME COMPONENTS`. + +> The bottom panel contains utility buttons: 1) Disconnect entity. 2) Delete entity. 3) Auto-fill template array. 4) Cascade auto-fill for all child connects in the hierarchy. + +--- + +`AutoEntityCreator` automatically creates an entity and binds it to the GameObject. In the inspector specify the `EcsEntityConnect` to use and the [world provider](#world-provider) where the entity should be created. + +
+Add component: Add Component > DragonECS > AutoEntityCreator. + +

+ +

+ +
+ +

+ +

+ +> The bottom panel includes helper buttons: 1) Auto-fill the connect reference. 2) Cascade auto-fill for all child instances in the hierarchy. + +
+ +# World Provider +`EcsWorldProvider` is a `ScriptableObject` wrapper over `TWorld` intended to expose a world instance via the Unity inspector. For simple scenarios the singleton provider `EcsDefaultWorldSingletonProvider` is sufficient. + +```c# +// The singleton provider is created automatically under "Assets/Resource". +EcsDefaultWorldSingletonProvider provider = EcsDefaultWorldSingletonProvider.Instance; +// ... + +EcsDefaultWorld world = new EcsDefaultWorld(); +// Set the world instance to the provider. +provider.Set(world); + +// ... + +// Get the world instance; the provider will create a default world if empty. +EcsDefaultWorld world = provider.Get(); + +EcsPipeline pipeline = EcsPipeline.New() + //... + // Inject the provider world into systems. + .Inject(world) + //... + .BuildAndInit(); +``` + +
+Example: provider implementation for a custom world type + +```c# +// Example implementation of a provider to expose a custom world type +[CreateAssetMenu(fileName = nameof(EcsMyWorldProvider), menuName = EcsConsts.FRAMEWORK_NAME + "/WorldProviders/" + nameof(EcsMyWorldProvider), order = 1)] +public class EcsMyWorldProvider : EcsWorldProvider { } + +// Example singleton provider implementation for a custom world type +public class EcsMyWorldSingletonProvider : EcsWorldProvider +{ + private static EcsMyWorldSingletonProvider _instance; + public static EcsMyWorldSingletonProvider Instance + { + get + { + if (_instance == null) { _instance = FindOrCreateSingleton("SingletonMyWorld"); } + return _instance; + } + } +} +``` + +
+ +
+Create provider asset: Asset > Create > DragonECS > WorldProviders > Select world type. + +

+ +

+ +
+ +

+ +

+ +
+ +# Pipeline templates +Pipelines and entities can be assembled from templates. Pipeline templates are modules implementing the `IEcsModule` interface. + +The package provides two pipeline template types by default: `ScriptablePipelineTemplate` and `MonoPipelineTemplate`. + +## ScriptablePipelineTemplate +Stored as a `ScriptableObject` asset. Create via `Asset > Create > DragonECS > ScriptablePipelineTemplate`. + +

+ +

+ +## MonoPipelineTemplate +Attachable to a `GameObject`. Inherits from `MonoBehaviour`. Add via `Add Component > DragonECS > MonoPipelineTemplate`. + +

+ +

+ +
+ +# EcsRootUnity +Lightweight Ecs root implementation for Unity. Builds a pipeline from pipeline templates. Derives from `MonoBehaviour`. Add via `Add Component > DragonECS > EcsRootUnity`. + +

+ +

+ + +
+ + +# FixedUpdate and LateUpdate +```c# +using DCFApixels.DragonECS; +using UnityEngine; +public class EcsRoot : MonoBehaviour +{ + private EcsPipeline _pipeline; + //... + private void Update() + { + // Standard pipeline run. + _pipeline.Run(); + } + private void FixedUpdate() + { + // Pipeline run for FixedUpdate. + _pipeline.FixedRun(); + } + private void LateUpdate() + { + // Pipeline run for LateUpdate. + _pipeline.LateRun(); + } + // ... +} +``` + +
+ +# Project documentation +A documentation window based on meta-attributes is available via `Tools > DragonECS > Documentation`. Documentation is generated on first open and when the `Update` button is pressed. + +

+ +

+ +
+ +# Settings window +The settings window exposes several options, including component display modes in the Inspector. At the bottom, toggles for framework define symbols are available. Open via `Tools > DragonECS > Settings`. + +

+ +

+ +
+ +# Reference Repairer +Some parts of the integration heavily use `[SerializeReference]`, which can lose type information after renames. The `Reference Repairer` tool collects assets with missing types and provides an interface to map new type names and repair collected assets. Open via `Tools > DragonECS > Reference Repairer`. +> If missing types have a `[MetaID(id)]` attribute, the tool attempts automatic mapping. +

+ +

+ +
+ +# FAQ +## Cannot add `EcsEntityConnect` or other components +This issue may appear after a package update. Recommended remediation steps: run `Assets -> Reimport All`, or close Unity, remove the project's `Library` folder and reopen the project.