(v0.50) DOTS Tutorial - Build a Multiplayer AR app
  • What is the Purpose of this DOTS Tutorial?
  • Important Notes For Using This Gitbook
  • Unity ECS
    • Intro to Unity ECS
    • Create a Unity ECS Project
    • Spawn and Move Prefabs
    • Spawn and Move Players
    • Spawn Bullets and Destroy Player
    • Publish Builds in Unity ECS
  • Unity DOTS Physics
    • Intro to Unity DOTS Physics
    • Use DOTS Physics for Prefabs, Players, and Bullets
    • Use DOTS Physics for Collisions
  • Unity DOTS NetCode
    • Intro to DOTS NetCode
    • Create a Network Connection using DOTS NetCode
    • Load a Game using DOTS NetCode
    • DOTS NetCode and Prefabs
    • DOTS NetCode and Player Prefabs
    • Use DOTS NetCode for Collisions and Destroying Bullet Prefabs
    • Dynamically Changing Ghosts Between Interpolated and Predicted
  • UI Builder and UI Toolkit
    • Intro to UI Toolkit
    • Create a ScreenManager
    • Style a View
    • Create a ListView
    • Responsive Game UI
    • Navigate Between Scenes Using ClientServerBootstrap
  • Multiplayer (NetCode+, UI Toolkit+)
    • Intro to Unity NetCode Multiplayer
    • Host or Join a Multiplayer Session on LAN
    • Broadcast a LAN Multiplayer Game
    • Keep Score and Update Game UI
    • Send Ghosts with NetCode Using Relevancy
  • AR Foundation
    • Intro to AR Foundation
    • Set Up AR Foundation and ARKit
    • Spawn a Player using AR Foundation
    • Update UI using AR Foundation
Powered by GitBook
On this page
  • What you'll develop on this page
  • Project setup
  • Packages setup
  • Sub Scene setup
  • Initializing game settings
  1. Unity ECS

Create a Unity ECS Project

Full workflows and code to set up an ECS project with the latest Unity Editor and compatible package versions

PreviousIntro to Unity ECSNextSpawn and Move Prefabs

Last updated 2 years ago

What you'll develop on this page

Basic game settings will be configured in a GameObject in a Sub Scene and can be viewed in the "Entity Inspector" at runtime.

Project setup

  • Install Unity Hub 3.1.2 if you do not have it already

  • Install Unity 2020 LTS if you do not have it already

    • Go to "Installs" on the left side of Unity Hub pop-up window

    • Click "Add" and choose 2020 LTS

    • Once 2020 LTS is downloaded, click on the three vertical dots menu (kebab menu) in the top right corner to add platform modules depending on your development and target platforms (OSX/Linux/Windows)

    • Include iOS Build Support if you plan on completing the AR Foundation section of this gitbook

  • Go to "Projects" in Unity Hub and click "New" in the top left corner of the window and select 2020 LTS and create a new 3D project, "Asteroids 3D XR Multiplayer"

Note For those on a Fedora system (does not apply to Mac or Windows)

  • Upon installing the burst compiler you might get a cascading error that began with blah blah... DllNotFoundException: libdl.so ...blah blah

  • /usr/lib64/libdl.so.2 and creating a symlink ln -s libdl.so.2 libdl.so solved the error

  • Editor needs a restart after adding the symlink

Packages setup

  • Once you're in Unity, navigate to Package Manager from "Window"

  • Within PackageManager find the little "gear" icon and select Advanced Project Settings

  • Check the box next to Enable Preview Packages and also Show Dependencies at the bottom of the window

    • This will allow you to view the preview packages that are included included in the package manifest

  • Outside of the Unity Editor, navigate to your project folder (wherever you saved it locally) and open manifest.json (inside the Packages folder) with Visual Studio code or your choice of editor

    • These are all the packages that are currently included in your project

  • We are now going to manually add a new package, the Hybrid Rendering package

  • Add the following line to the manifest somewhere between the curly braces and save:

    "com.unity.rendering.hybrid": "0.50.0-preview.44",
  • When you click back into the Editor, Unity will notice the updated manifest and "pull" down the hybrid renderer package we added (you'll see the "Importing" window pop-up with a loading bar)

    • Read the whole blog post if you want to be an ECS master, it is a great post!

  • Hybrid Renderer automatically pulls in ECS dependencies (everything you need for ECS)

  • You can see the dependencies of the package if you navigate back to the PackageManager in the Editor and select the Hybrid Renderer

  • A key dependency is Entities, which brings in even more additional dependencies

    • Entities v0.50.1-preview.2

      • Burst v1.6.4

      • Properties v1.7.0-preview

      • Properties UI v1.7.0-preview

      • Serialization v1.7.0-preview.1

      • Collections v1.2.3

      • Mathematics v1.2.5

      • Asset Bundle v1.0.0

      • Unity Web Request v2.3.1-preview

      • Performance testing API v2.3.1-preview

      • Mono Cecil v1.10.1

      • Jobs v0.50.0-preview.9

      • Scriptable Build Pipeline v1.19.2

      • Platform v0.50.0-preview.4

      • Roslyn Compiler for Unity v0.2.1-preview

      • Unity Profiling Core API v1.0.0

  • For the duration of this gitbook, we will almost exclusively be adding packages through the manifest

  • Now we will add support for Universal Render Pipeline

  • We could have also chosen to add High Definition Render Pipeline (HDRP), but we want to support mobile devices

  • Add the following line to the manifest somewhere between the curly braces and save

"com.unity.render-pipelines.universal": "10.9.0",

We now have an ECS project set up

  • created a new project

  • added hybrid renderer to the manifest

  • added universal render pipeline support

Sub Scene setup

First, some background:

Unity has no plans to sunset GameObject/MonoBehaviour functionality given how incredibly powerful and mature their workflows are. That's why Unity built tools and workflows for developers to support GameObject workflows while also utilizing DOTS (a sorta 2-in-1, you can use both!).

One such workflow is the use of "Sub Scenes." Unity gives you the ability to split your scene into several Sub Scenes, which you use to partition various GameObjects and Entities. When a Sub Scene window is open (a.k.a. 'editable'), it operates in "GameObject world." When a Sub Scene window is closed, it operates in "Entity-performant world" (so to speak).

This is how it works: This conversion of GameObjects into Entities within a Sub Scene takes place either when (1) you hit Play in Editor while the Sub Scene is open at the time, or when (2) you close the Sub Scene from its Inspector.

The conversion process itself shouldn't take long at all, even for massive scale environments like the Megacity demo.

External resources, if interested:

Now let's implement:

  • Right click on the Hierarchy window and choose "New Sub Scene" > "Empty Scene"

  • Name this Scene "ConvertedSubScene"

    • This will automatically create a new folder with the parent scene name

    • This will also automatically create a new folder called "SceneDependencyCache" which is used by Unity to help load/unload Sub Scenes

  • Select "ConvertedSubScene" in Hierarchy

  • Check out the settings in the Inspector

    • "Auto Load Scene" is selected true by default, which means this Sub Scene will automatically load its Entities when the scene is loaded

  • Double click on "ConvertedSubScene" in Assets/Scenes/SampleScene and hit the play button

    • Notice there are no cameras in the Sub Scene so nothing renders

  • Return to "SampleScene" in Assets/Scenes and hit the play button

    • Notice that the skybox renders because a camera is present

You can see how Unity is able to handle both GameObjects and Entities at runtime without adding a single Entity, Component, or System. The GameObject camera functions as expected even with a Sub Scene loaded into the scene.

Unity has release DOTS-specific Editor windows to help developers manage their DOTS projects. The windows available can be found in "Window" > "DOTS".

  • Let's combine all these views into a single view that has tabs for DOTS Hierarchy, Systems, Components, and Archetypes

    • We will use these windows to see:

      • Entities (hexagon icon)

      • Components (puzzle piece icon)

      • Systems (hexagon with arrows icon)

      • As well as "Archetypes" (types of entities) (hexagon with interior edges icon)

  • Let's checkout the amount of entities we currently have in our project by navigating to DOTS Hierarchy by clicking on the DOTS Hierarchy tab

    • You should see 3 entities (while the Sub Scene is "open")

  • Now let's close the Sub Scene by hitting the "close" button in the inspector when the ConvertedSubScene is selected in the Hierarchy

  • You Should now see 5 entities

  • Click through the 5 entities and notice how their components and values are shown in the Editor Inspector window

  • Think of the current 5 entities as autogenerated Unity.Entities "boiler plate" for our current scene / SubScene setup

We now are able to navigate Entities, Systems, Archetypes and see their associated data in the Inspector.

We now have a Sub Scene loading into our scene

  • We created a Sub Scene "ConvertedSubScene" in the Hierarchy

  • Created a "DOTS Window" containing the new DOTS Editor Views

  • Saw how the number of entities changes when a Sub Scene is open vs. closed because of the Sub Scene conversion work flow

Initializing game settings

First, some background:

Conversion Workflow

To use Unity’s DOTS technology, you need to create entities, components and systems.

The generation process that consumes GameObjects (authoring data) and generates entities and components (runtime data) is called conversion.

  • This process is the preferred way of authoring ECS data

  • It is a fundamental part of DOTS, and not something temporary

  • Conversion is only about data, there is no conversion process for code

The overall workflow looks like this:

  1. The Unity Editor is a user interface to work with authoring data

  2. The conversion from authoring data to runtime data happens in the Unity Editor

  3. The runtime (e.g. the game) should only ever have to deal with runtime data

Fundamental principles

Authoring data and runtime data are optimized for wildly different goals.

  • Authoring data is optimized for flexibility

    • Human understandability and editability

    • Version control (mergeability, no duplication)

    • Teamwork organization

  • Runtime data is optimized for performance

    • Cache efficiency

    • Loading time and streaming

    • Distribution size

A key observation is that nothing requires a 1:1 mapping between GameObjects and entities.

  • A single GameObject can turn into a set of entities, e.g. procedural generation

  • Multiple GameObjects can be aggregated into a single entity, e.g. LOD baking

  • Some GameObjects might have no purpose at runtime, e.g. level editing markers

The same can be said about components. A conversion system can read from any amount of Unity components and add any amount of ECS components to any amount of entities.

Key concepts

All those concepts get explained in further detail in the rest of this document, but it's useful to introduce some vocabulary beforehand.

  • Authoring scene A regular Unity scene, containing GameObjects, destined to be converted to runtime data.

  • Subscene A simple GameObject component that references an authoring scene and will either load the authoring scene (when the Subscene is in edit mode), or stream in the converted entity scene (when the Subscene is closed).

  • Entity scene The result of converting an authoring scene. Because entity scenes are the output of an asset import, they are stored in the Library folder. Entity scenes can be made of multiple sections, and each of those can be independently loaded.

  • LiveConversion When an authoring scene is loaded as GameObjects for editing, every change will trigger an update to the entity scene, making it look as if the entity scene was directly edited, we call this process LiveConversion.

🔑 Major Key Alert 🔑

Now let's implement:

  • Create a new folder called "Scripts and Prefabs" in the "Assets" folder within the Project window

  • Navigate to the "Scripts and Prefabs" folder, right click, choose "Create" > "ECS" > "Runtime Component Type", and name it "GameSettingsComponent"

    • This is the "Component" from Entity Component System

  • Copy the below code snippet into GameSettingsComponent.cs:

using Unity.Entities;

public struct GameSettingsComponent : IComponentData
{
    public float asteroidVelocity;
    public float playerForce;
    public float bulletVelocity;
    public int numAsteroids;
    public int levelWidth;
    public int levelHeight;
    public int levelDepth;
}

Make sure to first clear the file before pasting in this code snippet.

  • Components cannot store data pre-runtime. So, to set game settings in the Editor ("authoring"), we will need to use the conversion workflow

    • public float asteroidVelocity = 10f; (cannot set values in IComponentData)

  • Navigate to "ConvertedSubScene" and create a new Empty GameObject named "GameSettings"

    • This GameObject will hold a script that will allow us to "author" game settings in the Editor and have those values converted at runtime into the GameSettingsComponent

  • In "Scripts and Prefabs", right click, choose "Create" > "ECS" > "Authoring Component Type", and create "SetGameSettingsSystem"

    • "Authoring" will allow us to add data in the Editor before runtime

  • SetGameSettingsSystem.cs

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

public class SetGameSettingsSystem : UnityEngine.MonoBehaviour, IConvertGameObjectToEntity
{
    public float asteroidVelocity = 10f;
    public float playerForce = 50f;
    public float bulletVelocity = 500f;

    public int numAsteroids = 200;
    public int levelWidth = 2048;
    public int levelHeight = 2048;
    public int levelDepth = 2048;
    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        var settings = default(GameSettingsComponent);

        settings.asteroidVelocity = asteroidVelocity;
        settings.playerForce = playerForce;
        settings.bulletVelocity = bulletVelocity;

        settings.numAsteroids = numAsteroids;
        settings.levelWidth = levelWidth;
        settings.levelHeight = levelHeight;
        settings.levelDepth = levelDepth;
        dstManager.AddComponentData(entity, settings);
    }
}
  • If you ever want to set data before runtime in the Editor ("authoring") and have it exist at runtime as Component data for ECS to use, you will use a conversion workflow similar to above:

      1. Within the IConvertGameObjectToEntity use Convert() to take the MonoBehaviour data and set it to a Component during the conversion process

    • On the next page we show how to use [GenerateAuthoringComponent] to add IComponentData directly on GameObjects

  • Click on the "GameSettings" object in the Hierarchy, then in the Inspector click "Add Component" and select SetGameSettingsSystem to add the MonoBehaviour to the GameObject

  • Make sure it's added and then navigate back to "SampleScene"

  • Select "ConvertedSubScene" from the Hierarchy (make sure it's selected) and then click "Reimport" in Inspector

  • Navigate to the DOTS Hierarchy window and notice a new Entity with a GameSettingsComponent

  • The new Entity with a GameSettingComponent can also be seen via a new EntityArchetype

Nice! The Sub Scene has followed the Convert() process and we have added the GameSettingsComponent to the converted GameSettings GameObject

Remember, the GameSettings GameObject in our ConvertedSubScene automatically gets converted because it is a GameObject in a Sub Scene.

Our SetGameSettingsSystem set on that GameObject has "Convert()" triggered when going through the conversion workflow, which:

  1. takes the new Entity (which used to be the GameSettings GameObject) and

  2. adds a GameSettingsComponent to it, then:

  3. sets the GameSettingsComponent data to the data set in the Editor

...which results in an Entity with a GameSettingsComponent. We will use this Entity in the next section.

A different way to get GameObject data into an ECS Component

In the latest ECS release GameObjectConversionSystem can also look for classic Unity components. So you can add data to a GameObject through a normal MonoBehavior component, and then "search" for that MonoBehavior component in an EntityQuery.

Here's the "hello world" of conversion systems, that does a 1:1 conversion of all authoring components of a certain type to their ECS equivalent.

// Authoring component
class FooAuthoring : MonoBehaviour
{
    public float Value;
}

// Runtime component
struct Foo : IComponentData
{
    public float SquaredValue;
}

// Conversion system, running in the conversion world
class FooConversion : GameObjectConversionSystem
{
    protected override void OnUpdate()
    {
        // Iterate over all authoring components of type FooAuthoring
        Entities.ForEach((FooAuthoring input) =>
        {
            // Get the destination world entity associated with the authoring GameObject
            var entity = GetPrimaryEntity(input);

            // Do the conversion and add the ECS component
            DstEntityManager.AddComponentData(entity, new Foo
            {
                SquaredValue = input.Value * input.Value
            });
        });
    }
}

In a GameObjectConversionSystem, ForEach will not create jobs. It runs on the main thread, without Burst, and this allows accessing classic Unity without restraint. This is also why it doesn't require a call to .Run() or .Schedule().

Also note that the entity query looks for classic Unity components, in this case FooAuthoring that derives from MonoBehaviour. Since those are reference types, they do not require ref or in.

We now have "authored" data on a GameObject that's been converted to Component data on an Entity

  • We created GameSettingsComponent.cs as our IComponentData the ("C" in "ECS")

  • We created SetGameSettingsSystem.cs which uses Unity's Sub Scene Conversion Workflow

  • We created GameSettings GameObject in ConvertedSubScene and added SetGameSettings as a Component

  • We navigated to our DOTS Editor windows to see that the new Entity and its GameSettingsComponent have been added to the Entity list

git clone https://github.com/moetsi/Unity-DOTS-Multiplayer-XR-Sample/ git checkout 'Setting-up-a-Project-for-ECS'

Github branch link:

:

If interested, read up to the "Hybrid Renderer" section to learn what makes the Hybrid Renderer "hybrid"

Adding certain packages directly from the Package Manager window is no longer possible ()

is what happens if you do not add the Universal Render Pipeline (URP)

More discussion on difference between URP vs. HDRP can be

How is this helpful? Here's an example: Visual artists can build GameObject assets in Sub Scenes, as long as they have the Sub Scene window open in Editor. When done editing, the visual artist closes the Sub Scene window, which triggers the conversion of these GameObjects into Entities. The Entities can be streamed in and out as needed. The conversion-to-entities allows for enormous environments (as demo'd in the below). If all those entities had been game objects, it would absolutely destroy the performance of a normal authoring scene.

Unity's Megacity walkthrough: Watch this if you want a general understanding of the benefits of Sub Scenes.

Unity's post about Sub Scene conversion workflows: Read this if you want to be up to speed with the latest and greatest updates.

Procedural generation of Sub Scenes: Read this if you are hardcore.

If you are confused by Worlds and Systems read the section on .

From

It is worth the effort to read through the and wrap your head around Authoring/Conversion as it is a key part of ECS development

Unity's Talk on conversion workflows: Watch this if you want a more in-depth explanation (and/or prefer videos).

The Component type is an interface called

Create the that you will need

Create an IConvertGameObjectToEntity () with public fields that match IComponentData

From

Github branch link:

https://github.com/moetsi/Unity-DOTS-Multiplayer-XR-Sample/tree/Setting-up-a-project-for-ECS
Join our Discord for more info
https://unity3d.com/get-unity/download
From Giiba on our discord
in this blog post
explanation in this post
This error
found here
Megacity walkthrough
https://www.youtube.com/watch?v=j4rWfPyf-hk
https://forum.unity.com/threads/new-subscene-converttoentity-workflows.638785/
https://forum.unity.com/threads/generate-sub-scenes-programmatically.868984/#post-6598072
"System organization" at the bottom of the link here
Unity's ECS Conversion Workflow documentation
Conversion Workflow documentation
https://www.youtube.com/watch?v=TdlhTrq1oYk
IComponentData (link to Unity docs)
IComponentData
also an Interface, link to Unity docs
Conversion systems 101 in Unity Docs
https://github.com/moetsi/Unity-DOTS-Multiplayer-XR-Sample/tree/Setting-up-a-Project-for-ECS
Join our Discord for more info
"Authored" game settings data in a converted Sub Scene appears in the Entity Debugger
Enable preview packages and dependencies then add hybrid renderer package
Overview of selecting Entities in the PackageManager
Adding a Sub Scene to the scene and naming it "ConvertedSubScene"
DOTS specific Editor views to assist in development
Our DOTS Windows
Total entities while the Sub Scene is "open" (open Sub Scenes do not convert the GameObjects contained within the Sub Scene)
Create Scripts and Prefabs folder and GameSettingsComponent.cs
Create the SetGameSettingsSystem and add it to GameSettings GameObject
New entity created from our GameSettings GameObject in ConvertedSubScene