Unity DOTS concise tutorial

What is DOTS

First of all, let's first understand what is DOTS?

DOTS is Data-Oriented-Tech-Stack, the official Chinese translation is: multi-threaded data-oriented technology stack.

It mainly consists of three parts:

  1. Mission system
  2. Physical component system
  3. Burst compiler

The following picture is a screenshot of the introduction of Unite2019:

Therefore, DOTS is a set of high-efficiency technology stacks that integrate Job System (write multi-threaded code), ECS (write high-performance code), and Burst Compliler (compile and generate high-performance code). By using DOTS, Unity projects can be run more efficiently, which can be expressed as higher fps, lower battery consumption, and less heat on the mobile platform. In addition, you can check out another concise tutorial on this blog about ECS .

How to use DOTS

(1) Installation environment

Confirm the next version first. The latest Unity version is recommended here. The blogger here uses the official version of Unity 2019.3;

1. Open the menu bar-window->package manager, the Advanced drop-down on the right side switches to show preview package (as of now, 2020.2.9 is still the preview version), install: Burst, Entities, Jobs, Hybrid Renderer (for DOTS rendering Related), Unity Physics (high-performance physics components for DOTS)

2. Enable Entity Debugger (Debugger), menu bar -Window-Analysis-Entity Debugger, you can drag and drop the window to a suitable position to view debugging information;

(2) Create a simple example

(1) Create a sub-scene: create a new scene, create a Cube, remove the Box collider component, select and right-click New SubScene From Selection, of course, you can also create an empty object by yourself and mount the SubScene script.

After creation, a scene file and corresponding cache file will be automatically generated under Assets. You can change the name of the newly created SubScene under Assets. It is essentially a Unity Scene. The difference is that the parent node of the Cube is mounted. A SubScene script is attached to manage and mark this scene as a DOTS. SubScene.

Under the SubScene script, you can configure some settings, including the corresponding scene, panel hierarchy color, whether to automatically load the scene, close and enable editing of the sub-scene, save, etc. When you open the editor, you can freely edit and fill other content under the SubScene node. You can refer to the small racing project of project tiny, which will use the entire big map as a sub-scene. When editing is turned off, the child nodes of the entire sub-scene are not visible or editable, and are treated as a GameObject.

After opening the sub-scene for editing, check the Entity Debugger, click All Entities (Editor World) on the right to see some status information of the current sub-scene, refer to (1) 2. Figure

(2) Coding

Create a C# script, Rotate.cs, nothing but a structure, which will be used as data:

using Unity.Entities;
public struct Rotate:IComponentData{
  public float radiansPerSecond;
}

Create a second script, RotateAuthoring.cs, whose main function is to convert GameObeject to Entity:

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

public class RotateAuthoring :MonoBehaviour,IConvertGameObjectToEntity
{
    [SerializeField]
    private float degresPerSecond;

    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)    
    {        
        dstManager.AddComponentData(entity, new Rotate 
            { ratiansPerSecond = math.radians(degresPerSecond) });        
        dstManager.AddComponentData(entity, new RotationEulerXYZ());    
     }
}

The IConvertGameObjectToEntity interface is used to convert the current GameObject (Cube) into a DOTS entity, and then bind the data;

Among them, RotationEulerXYZ is the rotation of the transform. In order to improve performance, a set of components has been rewritten in DOTS to separate the rotation, position, and scaling of the original Transform.

The third script is RotateSystem, inherited from ComponentSystem, and its role is to act as an entity driver.

using Unity.Entities;
using Unity.Transforms;
public class RotateSystem : ComponentSystem
{    
    protected override void OnUpdate()    
    {        
        Entities.ForEach((ref Rotate rotate, ref RotationEulerXYZ euler)=>        
        {            
            euler.Value.y += rotate.ratiansPerSecond * Time.DeltaTime;
        });    
    }
}

Entities.ForEach is used to traverse all the current entities, and then assign the data to the entity for operation;

After writing the code, mount the second script RotateAuthoring on the Cube. Set the value of DegresPerSecond to 50:

Run the project and the cube starts to rotate. View status:

(3) Use JobSystem to optimize

Modify the RotateSystem.cs script:

using Unity.Entities;
using Unity.Jobs;
using Unity.Transforms;

public class RotateSystem : JobComponentSystem
{
    private struct RotateJob : IJobForEach<RotationEulerXYZ, Rotate>
    {
        public float deltaTime;
        public void Execute(ref RotationEulerXYZ euler, ref Rotate rotate)
        {
            euler.Value.y += rotate.ratiansPerSecond * deltaTime;
        }
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var job = new RotateJob { deltaTime = Time.DeltaTime };
        return job.Schedule(this, inputDeps);
    }
}

The main change is to change the inheritance to JobComponentSystem, add a RotateJob, and then call the job in OnUpdate;

(4) Use BurstCompile


Enable BurstCompile in the menu bar

Add the [BurstCompile] feature to the RotateJob structure in the RotateSystem code, you need to use Unity.Burst;

    [BurstCompile]
    private struct RotateJob : IJobForEach<RotationEulerXYZ, Rotate>
    {
        public float deltaTime;
        public void Execute(ref RotationEulerXYZ euler, ref Rotate rotate)
        {
            euler.Value.y += rotate.ratiansPerSecond * deltaTime;
        }
    }

(5) Verification


Open SubScene editing, and copy a large number of cubes, more than 3000. Save the sub-scene. Run, open the Status of the Unity editor to view:

We found that the frame rate is still very stable, but Batches soared to 3359. We also need to optimize away:

(6) Optimize Batches

Create a Material under the Project panel, name it cube, and check Enable GPU Instancing.

Select all cubes of the sub-scene, and assign materials to all cubes. Save the sub-scene, run it again, and find that the batches have been optimized and the frame rate has also been greatly improved.

summary

The performance improvement brought by DOTS is very objective. You can imagine some barrage games and tower defense games. Using DOTS, you can see the performance improvement very intuitively. At present, Unity is also vigorously promoting this set of development technology. I believe that more and more projects will use DOTS in the future and benefit from DOTS.

Guess you like

Origin blog.csdn.net/mango9126/article/details/105219215