# The Entities tutorial
This simple tutorial project teaches essential `Entities` package usage and related DOTS concepts.
*Only the very basics of the `Entities.Graphics` package are used. The `Netcode` and `Physics` packages are not used at all.*
The completed running project looks like this:

- Randomly colored tanks move on a plane and spin their turrets.
- The tanks shoot colored projectiles which bounce on the ground and despawn after a while.
**The [walkthrough](#walkthrough) below explains how to create the full tutorial project from scratch, step-by-step.**
**A pre-completed version of the tutorial project is found in the `Projects/EntitiesTutorial` directory.** Use the `TutorialSelector` window (opened from the `Tutorial` menu in the menubar) to jump between the completed steps.
| ⚠ WARNING |
| :- |
| Some features are initially used in a non-optimal or incorrect way before being corrected in subsequent steps, so be sure to absorb the full context before imitating the presented code. |
*Please report any bugs and points of confusion you encounter in the [DOTS Forum](https://forum.unity.com/forums/data-oriented-technology-stack.147/).*
# Steps
**Step 1: Spawn a single, immobile tank (a cube, a sphere, and a cylinder).**
Introduces instantiation of rendered entities using a baked "subscene".

**Step 2: Rotate the turret at a fixed rate.**
Introduces unmanaged systems (`ISystem`), queries, and `SystemAPI.Query`.

**Step 3: Move the tank along a random curvy path.**
Introduces `SystemBase` and scheduling a parallel job with `Entities.ForEach`.

**Step 4: Spawn cannon balls at the tip of the turret at a fixed interval.**
Introduces use of entity prefabs, referencing entities from other entities, and scheduling a single-threaded job with `IJobEntity`.

**Step 5: Move the cannon balls.**
Introduces aspects and scheduling a parallel job with `IJobEntity`.

**Step 6: Spawn many tanks.**
Introduces a pattern for "initialization" systems (systems that should only run once).

**Step 7: Randomly color the tanks and cannon balls.**
Introduces baking systems.

**Step 8: Prevent the tanks from firing when within a circle area around the origin.**
Introduces enableable components (`IEnableableComponent`), live conversion, and storing basic configuration data in a singleton.

**Step 9: Move the camera to follow a random tank. Change which tank is followed when the player hits space bar.**
Introduces input handling in a system and simple runtime coordination between ECS and GameObjects.

# Walkthrough
## Required Unity Version
This tutorial uses **2022.2.0b8**.
Look for that version (or a more recent patch release) in the list of Unity releases from the Unity Hub itself: "Installs" (left menu), "Install Editor" (top right), "Pre-releases" (tab).
Alternatively, you can manually download the **2022.2.0b8** version of the Unity editor from those direct links:
- [Windows Unity Editor 64-bit](https://beta.unity3d.com/download/9eb452e2ea43/Windows64EditorInstaller/UnitySetup64.exe)
- [Mac Unity Editor (Intel)](https://beta.unity3d.com/download/9eb452e2ea43/MacEditorInstaller/Unity.pkg)
- [Mac Unity Editor (Apple Silicon)](https://beta.unity3d.com/download/9eb452e2ea43/MacEditorInstallerArm64/Unity.pkg)
- [Linux Unity Editor](https://beta.unity3d.com/download/9eb452e2ea43/LinuxEditorInstaller/Unity.tar.xz)
## Using directives and provided code
> A remark about code inlined in this tutorial.
Every code snippet in this document is automatically extracted from a reference project, and the using directives from the whole file that includes the snippet are copied. As a consequence, note that you will encounter using directives which are not yet necessary at the point where they are introduced.
Also, pay close attention to the way we explicitly reference `UnityEngine` types. This is a convention used in this tutorial to clearly delineate the DOTS related types from the classic Unity ones.
Some files are provided in full, while some other are modifications of existing files where a `+` line (green) is to be added, a `-` line (red) is to be removed, and the other lines remain unchanged and only provide context.
Finally, make sure you read through the comments in the code as you copy the provided source files. Those comments contain a lot of important information about the purpose of each step and are an integral part of this tutorial.
## Project setup
> Create a new project, install the packages we need, and tune the settings.

1. Create a new project in the Unity Hub, using the 3D (URP) template. You will eventually have to download the template if you haven't used it before. Make sure you are using the right Editor version.
1. Once the project is loaded, click the button "Remove Readme Assets" in the "URP Empty Template" inspector. This will get rid of the folder "Assets/TutorialInfo" which we don't need for this tutorial. This inspector should be selected by default, but if it isn't just select `Assets/Readme.asset` in the Project window.
1. Only one package needs to be explicitly installed for this tutorial. The other packages will be pulled into the project as dependencies. Go to `Window > Package Manager`, click the `+` button on the top left and select "Add package by name". Set the "Name" field to "com.unity.entities.graphics" and leave the "Version" field blank then click the "Add" button and wait for the package and its dependencies to install.

1. In `Edit > Project Settings > Editor`, enable "Enter Play Mode Options" but leave the reload sub-options unchecked. For more information about what these options do, please follow these links:
* [Unity Manual - Configurable Enter Play Mode](https://docs.unity3d.com/Manual/ConfigurableEnterPlayMode.html)
* [Unity Blog - Enter Play Mode faster in Unity 2019.3](https://blog.unity.com/technology/enter-play-mode-faster-in-unity-2019-3)
Pay close attention to the implication of those settings on the use of static fields (cf. blog post).
 1. In the Project window, create the missing folders from the following list in the Assets folder: * Prefabs * Scenes (already created) * Scripts/Aspects * Scripts/Authoring * Scripts/Components * Scripts/MonoBehaviours * Scripts/Systems * Settings (already created)  ## Conversion settings > Setup the baking pipeline properly. The rest of this tutorial assumes that the "Scene View Mode" (in `Preferences/Entities`) is set to "Runtime Data":  ## Types accessibility This tutorial takes the convention to make all classes and structs internal. Internal types or members are accessible only within files in the same assembly, and this is the default accessibility level in C#. When working on larger projects which are split over multiple assemblies, explicit accessibility modifiers will be required. Discussing this is out of scope for this tutorial, and isn't specific to DOTS in any way. ## Step 1 - Authoring Scene > Create the scene from which ECS data will be constructed. 1. Make sure the SampleScene from the Scenes folder is currently open. (The following steps will only work on a scene which is saved as a file.) 1. Within the Hierarchy window, right click and select `New Subscene > Empty Scene...`. Name the new scene "EntityScene", and put it in `Scenes/SampleScene`.
 1. Right click "EntityScene" in the Hierarchy window, select `GameObject > 3D Object > Cube` and name the new GameObject "Tank". Set its Position to (0,0,0), Rotation to (0,0,0) and Scale to (1,1,1). 1. Right click "Tank" in the Hierarchy window, select `3D Object > Sphere` and name the new GameObject "Turret". Set its **Position to (0,0.5,0)**, **Rotation to (45,0,0)** and Scale to (1,1,1). 1. Right click "Turret" in the Hierarchy window, select `3D Object > Cylinder` and name the new GameObject "Cannon". Set its **Position to (0,0.5,0)**, Rotation to (0,0,0) and **Scale to (0.2,0.5,0.2)**. 1. Right click "Cannon" in the Hierarchy window, select `Create Empty` and name the new GameObject "SpawnPoint". Set its **Position to (0,1,0)**, **Rotation to (-90,0,0)** and Scale to (1,1,1). 1. You should now have something similar to the following screenshot.
 1. One last thing about that little tank is that each primitive contains by default a collider. We are not going to use those colliders, and they are discarded during baking anyway (conversion to entities) because we don't have a DOTS compatible physics engine in the project. But in the spirit of DOD, let's get rid of useless data: remove the Box Collider component from "Tank", remove the Sphere Collider component from "Turret", and remove the Capsule Collider from "Cannon". There is no collider on "SpawnPoint", so nothing to do there.

## Step 2 - Turret Rotation
> Introducing the concepts of unmanaged systems (`ISystem`), queries, idiomatic `foreach`.
1. Create a new file named "TurretRotationSystem.cs" in the folder "Scripts/Systems", put the following contents in there:
```c#
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
// Unmanaged systems based on ISystem can be Burst compiled, but this is not yet the default.
// So we have to explicitly opt into Burst compilation with the [BurstCompile] attribute.
// It has to be added on BOTH the struct AND the OnCreate/OnDestroy/OnUpdate functions to be
// effective.
[BurstCompile]
partial struct TurretRotationSystem : ISystem
{
// Every function defined by ISystem has to be implemented even if empty.
[BurstCompile]
public void OnCreate(ref SystemState state)
{
}
// Every function defined by ISystem has to be implemented even if empty.
[BurstCompile]
public void OnDestroy(ref SystemState state)
{
}
// See note above regarding the [BurstCompile] attribute.
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
// The amount of rotation around Y required to do 360 degrees in 2 seconds.
var rotation = quaternion.RotateY(SystemAPI.Time.DeltaTime * math.PI);
// The classic C# foreach is what we often refer to as "Idiomatic foreach" (IFE).
// Aspects provide a higher level interface than directly accessing component data.
// Using IFE with aspects is a powerful and expressive way of writing main thread code.
foreach (var transform in SystemAPI.Query

| 📝 NOTE |
| :- |
| The problem is that the `foreach` we created matches anything that has a transform, this causes every part of the tank hierarchy to rotate. We need to constrain it to only affect the rotation of the turret. |
1. Leave play mode.
1. Create a new C# source file named "Turret.cs" in the folder "Scripts/Components", put the following contents in there:
```c#
using Unity.Entities;
// An empty component is called a "tag component".
struct Turret : IComponentData
{
}
```
1. Create a new C# source file named "TurretAuthoring.cs" in the folder "Scripts/Authoring", put the following contents in there:
```c#
using Unity.Entities;
// Authoring MonoBehaviours are regular GameObject components.
// They constitute the inputs for the baking systems which generates ECS data.
class TurretAuthoring : UnityEngine.MonoBehaviour
{
}
// Bakers convert authoring MonoBehaviours into entities and components.
class TurretBaker : Baker

1. Modify the contents of the file named "TurretRotationSystem.cs" in the folder "Scripts/Systems" as follows:
```diff
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
[BurstCompile]
partial struct TurretRotationSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
}
[BurstCompile]
public void OnDestroy(ref SystemState state)
{
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var rotation = quaternion.RotateY(SystemAPI.Time.DeltaTime * math.PI);
+ // WithAll adds a constraint to the query, specifying that every entity should have such component.
+ foreach (var transform in SystemAPI.Query

1. Leave play mode.
## Step 3 - Tank movement
> Introducing `SystemBase` and `Entities.ForEach` parallelism.
1. Create a new C# source file named "Tank.cs" in the folder "Scripts/Components", put the following contents in there:
```c#
using Unity.Entities;
// Just like we did with the turret, we create a tag component to identify the tank (cube).
struct Tank : IComponentData
{
}
```
1. Create a new C# source file named "TankAuthoring.cs" in the folder "Scripts/Authoring", put the following contents in there:
```c#
using Unity.Entities;
class TankAuthoring : UnityEngine.MonoBehaviour
{
}
class TankBaker : Baker

1. Leave play mode.
## Step 4 - Cannon Balls
> Creating a prefab, referencing entities from other entities.
1. Create a new C# source file named "CannonBall.cs" in the folder "Scripts/Components", put the following contents in there:
```c#
using Unity.Entities;
using Unity.Mathematics;
// Same approach for the cannon ball, we are creating a component to identify the entities.
// But this time it's not a tag component (empty) because it contains data: the Speed field.
// It won't be used immediately, but will become relevant when we implement motion.
struct CannonBall : IComponentData
{
public float3 Speed;
}
```
1. Create a new C# source file named "CannonBallAuthoring.cs" in the folder "Scripts/Authoring", put the following contents in there:
```c#
using Unity.Entities;
using Unity.Rendering;
class CannonBallAuthoring : UnityEngine.MonoBehaviour
{
}
class CannonBallBaker : Baker

1. Modify the contents of the file named "Turret.cs" in the folder "Scripts/Components" as follows:
```diff
using Unity.Entities;
struct Turret : IComponentData
{
+ // This entity will reference the nozzle of the cannon, where cannon balls should be spawned.
+ public Entity CannonBallSpawn;
+ // This entity will reference the prefab to be spawned every time the cannon shoots.
+ public Entity CannonBallPrefab;
}
```
1. Modify the contents of the file named "TurretAuthoring.cs" in the folder "Scripts/Authoring" as follows:
```diff
using Unity.Entities;
class TurretAuthoring : UnityEngine.MonoBehaviour
{
+ public UnityEngine.GameObject CannonBallPrefab;
+ public UnityEngine.Transform CannonBallSpawn;
}
class TurretBaker : Baker

1. Create a new C# source file named "TurretAspect.cs" in the folder "Scripts/Aspects", put the following contents in there:
```c#
using Unity.Entities;
using Unity.Mathematics;
using Unity.Rendering;
// Instead of directly accessing the Turret component, we are creating an aspect.
// Aspects allows you to provide a customized API for accessing your components.
readonly partial struct TurretAspect : IAspect
{
// This reference provides read only access to the Turret component.
// Trying to use ValueRW (instead of ValueRO) on a read-only reference is an error.
readonly RefRO

## Step 5 - Cannon ball movement
> Introducing parallel jobs.
1. Create a new C# source file named "CannonBallAspect.cs" in the folder "Scripts/Aspects", put the following contents in there:
```c#
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
readonly partial struct CannonBallAspect : IAspect
{
// An Entity field in an aspect provides access to the entity itself.
// This is required for registering commands in an EntityCommandBuffer for example.
public readonly Entity Self;
// Aspects can contain other aspects.
readonly TransformAspect Transform;
// A RefRW field provides read write access to a component. If the aspect is taken as an "in"
// parameter, the field will behave as if it was a RefRO and will throw exceptions on write attempts.
readonly RefRW

## Step 6 - Spawning many tanks
> Dealing with initialization systems that should only run once.
1. Drag & drop the "Tank" GameObject from "EntityScene" to the "Assets/Prefabs" folder in the Project window.
1. Delete the "Tank" GameObject (now a prefab instance) from "EntityScene".
1. Create a new C# source file named "Config.cs" in the folder "Scripts/Components", put the following contents in there:
```c#
using Unity.Entities;
struct Config : IComponentData
{
public Entity TankPrefab;
public int TankCount;
public float SafeZoneRadius;
}
```
1. Create a new C# source file named "ConfigAuthoring.cs" in the folder "Scripts/Authoring", put the following contents in there:
```c#
using Unity.Entities;
class ConfigAuthoring : UnityEngine.MonoBehaviour
{
public UnityEngine.GameObject TankPrefab;
public int TankCount;
public float SafeZoneRadius;
}
class ConfigBaker : Baker

| 📝 NOTE |
| :- |
| The "SafeZoneRadius" is not used yet, but will be relevant for a later step. |
1. Create a new C# source file named "TankSpawningSystem.cs" in the folder "Scripts/Systems", put the following contents in there:
```c#
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Rendering;
[BurstCompile]
partial struct TankSpawningSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
}
[BurstCompile]
public void OnDestroy(ref SystemState state)
{
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var config = SystemAPI.GetSingleton

1. Leave play mode.
## Step 7 - Colored tanks and cannon balls
> Advanced baking, introducing baking systems.
ECS components can control the inputs to the shaders used for rendering. Creating our own shaders (via shadergraph) and mapping custom ECS components to their inputs is out of scope for this tutorial, but we will use an already existing component called `URPMaterialPropertyBaseColor`. As the name implies, it allows controlling the base color of a standard URP material.
Our tanks are made of three primitives (tank, turret, cannon), and each of those entities need to have the `URPMaterialPropertyBaseColor` component added.
To do so, open the Tank prefab and select all three primitives in the hierarchy (tank, turret, cannon) but not the SpawnPoint transform. Since it doesn't have a renderer, it doesn't need a color.
With the three primitives selected, use the "Add Component" button in the inspector to add a `URPMaterialPropertyBaseColorAuthoring` component.
1. Enter play mode, notice that the tanks are now completely black (which is the default 0,0,0,0 value of the authoring component we just added).

1. Leave play mode.
1.
| 📝 NOTE |
| :- |
| The EntityCommandBuffer used by the system below requires a query to specify which entities should be targeted by SetComponentForLinkedEntityGroup.

1. Leave play mode.
1. Modify the contents of the file named "CannonBallAuthoring.cs" in the folder "Scripts/Authoring" as follows:
```diff
using Unity.Entities;
using Unity.Rendering;
class CannonBallAuthoring : UnityEngine.MonoBehaviour
{
}
class CannonBallBaker : Baker

1. Leave play mode.
## Step 8 - Safe zone
> Config singleton, live conversion.
1. Create a new C# source file named "Shooting.cs" in the folder "Scripts/Components", put the following contents in there:
```c#
using Unity.Entities;
// This is a tag component that is also an "enableable component".
// Such components can be toggled on and off while remaining present on the entity.
// Doing so is a lot more efficient than adding and removing the component.
struct Shooting : IComponentData, IEnableableComponent
{
}
```
1. Modify the contents of the file named "TurretAuthoring.cs" in the folder "Scripts/Authoring" as follows:
```diff
using Unity.Entities;
class TurretAuthoring : UnityEngine.MonoBehaviour
{
public UnityEngine.GameObject CannonBallPrefab;
public UnityEngine.Transform CannonBallSpawn;
}
class TurretBaker : Baker


1. Still in play mode, select the "Config" authoring GameObject and modify the "Safe Zone Radius". Notice that the changes are reflected in real time thanks to "Live Conversion" (see the DOTS menu).
1. Leave play mode.
## Step 9 - Camera follow
> Simple interaction between ECS and GameObjects at runtime.
1. Create a new C# source file named "CameraSingleton.cs" in the folder "Scripts/MonoBehaviours", put the following contents in there:
```c#
// There are many ways of getting access to the main camera, but the approach using
// a singleton (as we use here) works for any kind of MonoBehaviour.
class CameraSingleton : UnityEngine.MonoBehaviour
{
public static UnityEngine.Camera Instance;
void Awake()
{
Instance = GetComponent

1. Leave play mode.
## Congratulations!
You reached the end of this tutorial! Go get some cake and celebrate!
The core of an entity query consists a set of component types, and the query provides a filtered view of only the entities matching that set.
For more information about entity queries, see the [package documentation](https://docs.unity3d.com/Packages/com.unity.entities@latest/index.html?subfolder=/manual/ecs_entity_query.html). |
Modify the contents of the file named "TankSpawningSystem.cs" in the folder "Scripts/Systems" as follows:
```diff
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Rendering;
[BurstCompile]
partial struct TankSpawningSystem : ISystem
{
+ // Queries should not be created on the spot in OnUpdate, so they are cached in fields.
+ EntityQuery m_BaseColorQuery;
[BurstCompile]
public void OnCreate(ref SystemState state)
{
+ // This system should not run before the Config singleton has been loaded.
+ state.RequireForUpdate