DragonECS integration with Unity
Go to file
2026-04-20 19:38:36 +08:00
src fix 2026-04-20 19:38:09 +08:00
.gitattributes Initial commit 2023-03-19 14:18:59 +08:00
.gitignore Update .gitignore 2025-01-06 10:56:30 +08:00
DragonECS-Unity.asmdef update ui 2024-09-11 10:37:25 +08:00
DragonECS-Unity.asmdef.meta Init commit/Add systems debug/Add new runners 2023-03-26 11:20:02 +08:00
LICENSE.md add .md extension for LICENSE 2025-03-14 14:23:27 +08:00
LICENSE.md.meta add .md extension for LICENSE 2025-03-14 14:23:27 +08:00
package.json up version 0.5.22 2026-04-20 19:38:36 +08:00
package.json.meta Remove obsolete code templates 2023-05-30 04:36:55 +08:00
README-RU.md update readme 2026-04-20 16:35:30 +08:00
README-RU.md.meta rename readme 2024-03-11 01:55:46 +08:00
README.md update readme 2026-04-20 16:35:30 +08:00
README.md.meta Init commit/Add systems debug/Add new runners 2023-03-26 11:20:02 +08:00
src.meta Init commit/Add systems debug/Add new runners 2023-03-26 11:20:02 +08:00

Version GitHub Discord QQ

Integration with Unity for DragonECS

Readme Languages:

Русский

English(WIP)

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, the Russian README contains additional details.

//https://gist.github.com/DCFApixels/c250f2561f09e09ab3e6a4bd4f3013cb#file-unitycomponenttemplates-cs

Table of contents


Installation

Versioning semantics - Open

Environment

Requirements:

  • Dependency: DragonECS
  • Minimum C# version: 8.0
  • Minimum Unity version: 2021.2.0

Unity Installation

  • Unity package

Installation as a Unity package is supported by adding the Git URL in PackageManager:

https://github.com/DCFApixels/DragonECS-Unity.git

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. 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.

// 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.

_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(...).


  • WorldQueriesMonitor

Located together with WorldMonitor, shows a list of all Where queries that systems have executed. At the top there is a search field for filtering queries by component names. The search string can be split with a / character to search for multiple components at once. Next to each Where query there is a Snapshot button; clicking it opens a window showing a list of all entities that currently match the query mask.


  • 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 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 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:
// Add [Serializable] attribute to the component type.
[Serializable]
struct SomeComponent : IEcsComponent { /* ... */ }
class SomeComponentTemplate : ComponentTemplate<SomeComponent> { }
// Same for tag components.
[Serializable]
struct SomeTagComponent : IEcsTagComponent { }
class SomeTagComponentTemplate : TagComponentTemplate<SomeTagComponent> { }
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.

public struct Health : IEcsComponent, ITemplateNode
{
    public float Points;
    public void Apply(short worldID, int entityID)
    {
        EcsPool<Health>.Apply(worldID, entityID) = this;
    }
}

The section Inspector Customization describes customization of component display and usage outside of entity templates.

Custom template implementation

If built-in ComponentTemplate<T> or TagComponentTemplate<T> 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.

[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<SomeComponent>.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]:

// Display a field as a component, customizable with meta attributes.
// Similar to components in MonoEntityTemplate or ScriptableEntityTemplate.
[SerializeField, ComponentTemplateField]
private SomeComponent _someComponent1;
// For SerializeReference adds a button to pick available ITemplateNode implementation
[SerializeReference, ComponentTemplateField]
private ITemplateNode _someComponent1;

Wrapper ComponentTemplateProperty:

// Wrapper around ITemplateNode, similar to the ComponentTemplateField example.
private ComponentTemplateProperty _someComponent2;

Both approaches work for arrays too:

[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.

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 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<TWorld> 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.

// 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
// 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<EcsMyWorld> { }

// Example singleton provider implementation for a custom world type
public class EcsMyWorldSingletonProvider : EcsWorldProvider<EcsMyWorld>
{
    private static EcsMyWorldSingletonProvider _instance;
    public static EcsMyWorldSingletonProvider Instance
    {
        get
        {
            if (_instance == null) { _instance = FindOrCreateSingleton<EcsMyWorldSingletonProvider>("SingletonMyWorld"); }
            return _instance;
        }
    }
}
Create provider asset: Asset > Create > DragonECS > WorldProviders > Select world type.


Pipeline template

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

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();
    }
    // ...
}

Inspector Customization

Inspector Attributes

  • [ReferenceDropDown] - Applied to a field with [SerializeReference]. Adds a type selection button from a list. The set of available types can be restricted by passing a list to the constructor.

  • [ReferenceDropDownWithout] - Used together with [ReferenceDropDown] to exclude the specified types (and their descendants) from the selection list.

  • [DragonMetaBlock] - Displays the value in the inspector similarly to how components are displayed in entity templates. Takes meta-attributes into account (MetaGroup, MetaColor, MetaDescription, MetaID, etc.).

Behavior of MetaAttributes

  • Hierarchical grouping of items in the Add Component menu or [ReferenceDropDown] is defined via [MetaGroup].
  • The component color in the inspector is determined by the type name by default. The coloring mode can be changed in the settings window. An explicit color is set via [MetaColor].
  • When the type name matches the file name (or when [MetaID] is present), a file icon appears next to the delete button: a single click selects the script in the project, a double click opens it.
  • If [MetaDescription] is specified, a tooltip icon with the description text is displayed next to it.
  • When restoring a Missing Reference using Reference Repairer, the tool searches for a match between the old and new type names by the [MetaID(id)] attribute.

Examples:

DragonMetaBlock attribute:

// Display of the field customizable via meta-attributes.
// Similar to components in MonoEntityTemplate or ScriptableEntityTemplate.
[DragonMetaBlock]
public SomeComponent Component;

// Can be applied to any field of any type.
[DragonMetaBlock]
public Foo Foo;

ReferenceDropDown and ReferenceDropDownWithout:

// Adds a button to select an implementation of ITemplateNode from a drop-down list.
[SerializeReference]
[ReferenceDropDown]
public ITemplateNode Template;
// Also applicable to any field of any type.
// The list will contain only type Foo and its descendants, excluding FooExc and its descendants.
[SerializeReference]
[ReferenceDropDown(typeof(Foo))]
[ReferenceDropDownWithout(typeof(FooExc))]
public object Template;

Combination and other use cases:

// Attributes can be combined.
[DragonMetaBlock]
[ReferenceDropDown]
public ITemplateNode Template;

// A wrapper over ITemplateNode, similar to the example above.
public ComponentTemplateProperty Template;

// Attributes work correctly with arrays and lists.
[DragonMetaBlock]
[ReferenceDropDown]
public ITemplateNode[] Template;

Jobs Support

DragonECS is compatible with Unity's Job system by default. Example:

EcsWorld _world;
class Aspect : EcsAspect
{
    // Pool for unmanaged components.
    public EcsValuePool<Cmp> Cmps = Inc;
}
public void Run()
{
    var job = new Job()
    {
        // Same as Where, but returns an unmanaged entity list.
        Entities = _world.WhereUnsafe(out Aspect a),
        // Convert the pool to its unmanaged version
        Cmps = a.Cmps.AsNative(),
        X = 10f,
    };
    JobHandle jobHandle = job.Schedule(job.Entities.Count, 64);
    jobHandle.Complete();
}
// Unmanaged component.
public struct Cmp : IEcsValueComponent
{
    public float A;
}
private struct Job : IJobParallelFor
{
    public EcsUnsafeSpan Entities;
    public NativeEcsValuePool<Cmp> Cmps;
    public float X;
    public Job(EcsUnsafeSpan entities, float x)
    {
        Entities = entities;
        X = x;
    }
    public void Execute(int index)
    {
        var e = Entities[index];
        Cmps[e].A += X;
    }
}

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.