A grey cube on blank graph paper beside a closed laptop
| |

Unity DOTS & ECS Tutorial 2026

This is a small slice of Unity’s Data-Oriented Technology Stack, not a performance test. You will bake one authoring component into an entity and rotate that entity from a system. There are no frame-time numbers here. If you want a crowd, a projectile storm, or a comparison against GameObjects, build that later, on your own machine, and measure it yourself.

The Entities package moves. The steps below follow the authoring pattern in Unity’s Entities manual for the 6.6 package line: an IComponentData struct, a Baker on a MonoBehaviour, and an ISystem that queries LocalTransform. Open the manual for the package version you actually installed. Menu names, the GetEntity signature, and whether you need a subscene can differ. The manual is the source of truth: https://docs.unity3d.com/Packages/com.unity.entities@6.6/manual/baking.html

Install only what this slice needs

In Package Manager, add the Entities package (com.unity.entities). Unity may pull companion packages such as Collections and Mathematics. Accept the set your editor resolves. If the package name is missing or renamed in your Unity version, stop and use the official install steps instead of an old forum command.

Create an empty 3D scene. Put a cube at the origin so you have something to look at. You will not spin the cube from Update on the MonoBehaviour. That script’s only job is to hold a number the baker can read.

Add the data and the baker

A component in this workflow is a struct of data. A system is the code that reads and writes it. The GameObject in the scene is authoring data. Baking turns it into an entity.

Create a script like this. Namespaces and GetEntity overloads should match your package. If this file does not compile, diff it against the “authoring and baking” page for your version rather than adding random usings.

using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;

public struct RotationSpeed : IComponentData
{
    public float RadiansPerSecond;
}

public class RotationSpeedAuthoring : MonoBehaviour
{
    public float DegreesPerSecond = 90f;

    class Baker : Baker<RotationSpeedAuthoring>
    {
        public override void Bake(RotationSpeedAuthoring authoring)
        {
            Entity entity = GetEntity(TransformUsageFlags.Dynamic);
            AddComponent(entity, new RotationSpeed
            {
                RadiansPerSecond = math.radians(authoring.DegreesPerSecond)
            });
        }
    }
}

TransformUsageFlags.Dynamic tells baking that the transform will change at runtime. The baker copies your degrees-per-second field into radians on the entity. It does not run every frame. If you change the field on the prefab, baking is supposed to run again. The manual explains dependency tracking. Use DependsOn when you read data from outside the authoring component, or live baking can go stale. You do not need that for this one field.

Put RotationSpeedAuthoring on the cube. Leave the speed at 90, or type another value. The number is yours. Nothing in this tutorial claims it is a good default for a shipped game.

Bake it in a subscene

Current Entities workflows bake authoring GameObjects that live in a subscene. Create a subscene, move the cube into it, and save. The editor UI for creating a subscene has moved before, so use the subscene page in the manual if the menu is not where a video said it was.

Enter Play Mode. The cube should yaw. If it does not:

  • Confirm the cube is inside the subscene, not only sitting next to it.
  • Confirm the authoring component is on that object and the field is not zero.
  • Look at the console. A missing package or a baker exception will stop the spin even when the scene looks fine.
  • Open the Entities hierarchy window if your package provides one, and check that the entity has both a transform and RotationSpeed. Window names differ. Search the manual for the entity inspector rather than guessing a menu.

The system that actually spins it

Add a second script:

using Unity.Entities;
using Unity.Transforms;

public partial struct RotationSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        float deltaTime = SystemAPI.Time.DeltaTime;
        foreach (var (transform, speed) in
                 SystemAPI.Query<RefRW<LocalTransform>, RefRO<RotationSpeed>>())
        {
            transform.ValueRW = transform.ValueRO.RotateY(
                speed.ValueRO.RadiansPerSecond * deltaTime);
        }
    }
}

The struct is partial because Entities generates code around ISystem. The query selects entities that have both components. RefRW is the transform you write. RefRO is the speed you only read. RotateY is a LocalTransform helper in the transforms package. If your version does not have that method, apply a yaw with the mathematics API the manual shows, and keep the rest of the query.

The official sample also puts a Burst compile attribute on OnUpdate. Skip it until the cube spins. Burst is optional for learning the data path. If you add it later, install the Burst package and copy the attribute from the manual for your version. This article will not tell you that Burst makes the scene faster. Time it in your project if you care.

Play again. Change DegreesPerSecond, return to edit mode so baking can refresh, and play. The spin should follow the field. That loop, authoring value to baked component to system, is the whole lesson.

What not to add yet

Do not convert your player, your UI, or your physics in the same afternoon. GameObject workflows and entity workflows can exist in one project, but every bridge is extra API. The manual has pages on linking the two. Read those when you have a reason, such as a crowd of props that only move.

Do not copy a “millions of units” sample and treat it as a benchmark against your old scene. Different meshes, different work per entity, and different hardware make that comparison meaningless unless you set it up yourself.

A sensible second slice, still small, is a second component, such as a height offset, and a second system that only runs when that component exists. You will learn more from two queries you understand than from a framework you pasted.

When the cube yaws from RotationSpeed and nowhere else, stop. You have used baking, a component, and a system. That is enough DOTS for one day.

Similar Posts

Leave a Reply

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