Unity ECS Templates & Code Examples

6+

How many times when working with ECS you had to open a system that you’ve created before to copy-paste the implementation? Unfortunately, Unity ECS comes not only with performance by default, but also with a lot of boilerplate by default.

For reducing the boilerplate with ECS, I’ve created the project called UnityECSEntityBuilder that helps you creating & modifying the entities. However, I’m still reusing a lot of code that I write, so I decided to collect all the templates that you can easily copy-paste into your project when creating a new system / component.

So just add it to your favorites and use.

Components

IComponentData

public struct MyReadOnlyExampleComponent : IComponentData
    {
        // your parameters
    }

IBufferElementData

public struct MyBufferElementData : IBufferElementData
    {
        // your parameters
    }

ISystemStateComponentData

public struct MySystemStateComponentData : ISystemStateComponentData
    {
        // your parameters
    }

ISharedComponentData

public struct MySharedComponentData : ISharedComponentData
    {
        // your parameters
    }

Systems

System | ForEach | MainThread

public class MyExampleSystem : SystemBase
    {
        protected override void OnUpdate()
        {
            Entities
                .WithoutBurst()
                .ForEach((Entity entity, in MyReadOnlyExampleComponent component) =>
                {
                    // do your magic
                })
                .Run();
        }
    }

System | ForEach | MainThread | EntityCommandBuffer

    public class MyExampleSystem : SystemBase
    {
        protected override void OnUpdate()
        {
            var entityCommandBuffer  = new EntityCommandBuffer(Allocator.TempJob);
            
            Entities
                .WithoutBurst()
                .ForEach((Entity entity, in MyReadOnlyExampleComponent component) =>
                {
                    // do your magic
                    entityCommandBuffer.AddComponent<MyReadWriteExampleComponent>(entity);
                })
                .Run();
            
            entityCommandBuffer.Playback(EntityManager);
            entityCommandBuffer.Dispose();
        }
    }

System | ForEach | Parallel

    public class MyExampleSystem : SystemBase
    {
        protected override void OnUpdate()
        {
            Dependency = Entities
                .ForEach((Entity entity, in MyReadOnlyExampleComponent component) =>
                {
                    // do your magic
                })
                .ScheduleParallel(Dependency);
        }
    }

System | ForEach | Parallel | EntityCommandBuffer

public class MyExampleSystem : SystemBase
    {
        private EndSimulationEntityCommandBufferSystem m_endSimulationEntityCommandBufferSystem;

        protected override void OnCreate()
        {
            m_endSimulationEntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
        }

        protected override void OnUpdate()
        {
            var entityCommandBuffer = m_endSimulationEntityCommandBufferSystem.CreateCommandBuffer().AsParallelWriter();

            Dependency = Entities
                .ForEach((Entity entity, int entityInQueryIndex, in MyReadOnlyExampleComponent component) =>
                {
                    // do your magic
                    entityCommandBuffer.AddComponent<MyReadWriteExampleComponent>(entityInQueryIndex, entity);
                })
                .ScheduleParallel(Dependency);

            m_endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(Dependency);
        }
    }

System | Job.WithCode

public class MyExampleSystem : SystemBase
    {
        protected override void OnUpdate()
        {
            Dependency = Job.WithCode(() =>
            {
                // do you magic
            }).Schedule(Dependency);
        }
    }

System | IJob

[BurstCompile]
    public struct MyExampleJob : IJob
    {
        public void Execute()
        {
            // do your magic
        }
    }

    public class MyExampleSystem : SystemBase
    {
        protected override void OnUpdate()
        {
            Dependency = new MyExampleJob().Schedule(Dependency);
        }
    }

System | IJobChunk

[BurstCompile]
    public struct MyExampleJob : IJobChunk
    {
        [ReadOnly]
        public EntityTypeHandle entityTypeHandle;

        [ReadOnly]
        public ComponentTypeHandle<MyReadOnlyExampleComponent> readOnlyComponentHandle;

        public ComponentTypeHandle<MyReadWriteExampleComponent> readWriteComponentHandle;

        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var entities = chunk.GetNativeArray(entityTypeHandle);
            var readOnlyComponent = chunk.GetNativeArray(readOnlyComponentHandle);
            var readWriteComponent = chunk.GetNativeArray(readWriteComponentHandle);

            for (var i = 0; i < chunk.Count; i++)
            {
                var entity = entities[i];

                // do your magic
            }
        }
    }

    public class MyExampleSystem : SystemBase
    {
        private EntityQuery m_query;

        protected override void OnCreate()
        {
            m_query = GetEntityQuery(
                ComponentType.ReadOnly<MyReadOnlyExampleComponent>(),
                ComponentType.ReadWrite<MyReadWriteExampleComponent>()
            );
        }

        protected override void OnUpdate()
        {
            Dependency = new MyExampleJob
            {
                entityTypeHandle = GetEntityTypeHandle(),
                readOnlyComponentHandle = GetComponentTypeHandle<MyReadOnlyExampleComponent>(true),
                readWriteComponentHandle = GetComponentTypeHandle<MyReadWriteExampleComponent>()
            }.Schedule(m_query, Dependency);
        }
    }

System | IJobChunk | EntityCommandBuffer

[BurstCompile]
    public struct MyExampleJob : IJobChunk
    {
        [ReadOnly]
        public EntityTypeHandle entityTypeHandle;

        [ReadOnly]
        public ComponentTypeHandle<MyReadOnlyExampleComponent> readOnlyComponentHandle;

        public ComponentTypeHandle<MyReadWriteExampleComponent> readWriteComponentHandle;

        public EntityCommandBuffer.ParallelWriter ecb;

        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var entities = chunk.GetNativeArray(entityTypeHandle);
            var readOnlyComponent = chunk.GetNativeArray(readOnlyComponentHandle);
            var readWriteComponent = chunk.GetNativeArray(readWriteComponentHandle);

            for (var i = 0; i < chunk.Count; i++)
            {
                var entity = entities[i];

                // do your magic
                ecb.AddComponent<MyExampleComponent>(firstEntityIndex + i, entity);
            }
        }
    }

    public class MyExampleSystem : SystemBase
    {
        private EntityQuery m_query;
        private EndSimulationEntityCommandBufferSystem m_endSimulationEntityCommandBufferSystem;

        protected override void OnCreate()
        {
            m_query = GetEntityQuery(
                ComponentType.ReadOnly<MyReadOnlyExampleComponent>(),
                ComponentType.ReadWrite<MyReadWriteExampleComponent>()
            );

            m_endSimulationEntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
        }

        protected override void OnUpdate()
        {
            var entityCommandBuffer = m_endSimulationEntityCommandBufferSystem.CreateCommandBuffer().AsParallelWriter();
            
            Dependency = new MyExampleJob
            {
                ecb = entityCommandBuffer,
                entityTypeHandle = GetEntityTypeHandle(),
                readOnlyComponentHandle = GetComponentTypeHandle<MyReadOnlyExampleComponent>(true),
                readWriteComponentHandle = GetComponentTypeHandle<MyReadWriteExampleComponent>()
            }.Schedule(m_query, Dependency);
            
            m_endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(Dependency);
        }
    }

Component System Groups

[UpdateInGroup(typeof(SimulationSystemGroup))]
    public class MyComponentSystemGroup : ComponentSystemGroup
    {
    }

Entity Query

Simple query

    public class MyExampleSystem : SystemBase
    {
        private EntityQuery m_query;

        protected override void OnCreate()
        {
            m_query = GetEntityQuery(
                typeof(MyReadOnlyExampleComponent),
                typeof(MyReadWriteExampleComponent)
            );
        }
    }

Query specifying ReadOnly / ReadWrite access

For explanations regarding ReadOnly / ReadWrite components, have a look at this article.

public class MyExampleSystem : SystemBase
    {
        private EntityQuery m_query;

        protected override void OnCreate()
        {
            m_query = GetEntityQuery(
                ComponentType.ReadOnly<MyReadOnlyExampleComponent>(),
                ComponentType.ReadWrite<MyReadWriteExampleComponent>()
            );
        }
    }

Query with filtering components

public class MyExampleSystem : SystemBase
    {
        private EntityQuery m_query;

        protected override void OnCreate()
        {
            m_query =GetEntityQuery(new EntityQueryDesc
            {
                All = new ComponentType[]
                {
                    typeof(CompositeScale)
                },
                Any = new ComponentType[]
                {
                    ComponentType.ReadOnly<Scale>(),
                    ComponentType.ReadOnly<NonUniformScale>(),
                    ComponentType.ReadOnly<ScalePivot>(),
                    ComponentType.ReadOnly<ScalePivotTranslation>()
                }
            });
        }
    }
6+

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *