U3DC.COM | 优三帝研究院

Menu

Unity DOTS简明教程

什么是DOTS

首先,先来了解下什么是DOTS?

DOTS是Data-Oriented-Tech-Stack,官方中文翻译是:多线程式数据导向型技术堆栈。

它主要由三部分组成:

  1. 任务系统
  2. 实体组件系统
  3. Burst编译器

下图是Unite2019的介绍截图:

所以,DOTS是一套集合型的高效技术堆栈,整合了Job System(编写多线程代码)、ECS(编写高性能代码)、Burst Compliler(编译生成高性能代码)。通过使用DOTS可以让Unity项目跑的更高效,在移动平台上可以表现为更高的fps,更低的电池消耗,更小的发热。另外关于ECS可以查看本博客的另一篇简明教程

如何使用DOTS

(一)安装环境

先确认下版本,这里推荐最新Unity版本,博主这里用的是Unity2019.3正式版;

1.打开菜单栏-window->package manager,右侧的Advanced下拉切换为show preview package(截至目前2020.2.9依旧是预览版),安装:Burst、Entities、Jobs、Hybrid Renderer(用于DOTS的渲染相关)、Unity Physics(用于DOTS的高性能物理组件)

2.启用Entity Debugger(调试器),菜单栏-Window-Analysis-Entity Debugger,可以自行拖拽窗口到合适位置方便查看调试信息;

(二) 创建一个简单实例

(1)创建子场景:新建一个场景,创建一个Cube,移除Box collider组件,选中并右键New SubScene From Selection,当然也可以自行创建一个空物体,挂载SubScene脚本。

创建后则会自动在Assets下产生一个场景文件及对应的缓存文件。可以在Assets下自行更改刚创建的SubScene的名称,本质上还是一个Unity Scene,不一样的是Cube所挂载的父节点,多挂了一个SubScene脚本而已,用于管理和标记此场景是一个DOTS的SubScene。

在SubScene脚本下,可以进行一些配置,包括对应的场景、面板hierarchy 颜色,是否自动载入场景,关闭和启用编辑子场景,保存等。打开编辑时,可以在SubScene节点下自由编辑填充其他内容,可以参考project tiny 的小赛车项目,里面就将整个大地图就被作为了一个子场景。关闭编辑时,则整个子场景的子节点不可见,也不可编辑,被当作一个GameObject。

打开子场景编辑后,查看Entity Debugger,点击右边的All Entities(Editor World)可以看到当前子场景的一些状态信息,参考(一)2.图

(2)编码

创建一个C#脚本,Rotate.cs,没什么,就是一个结构体,它将作为数据:

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

创建第二个脚本,RotateAuthoring.cs,主要作用是将GameObeject转化为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());
    }
}

IConvertGameObjectToEntity接口用于将当前的GameObject(Cube)进行转换为DOTS的entity,然后绑定数据;

其中RotationEulerXYZ是transform的旋转,为了提高性能,DOTS里重写了一套组件,将原来的Transform里的旋转、位置、缩放等都单独出来。

第三个脚本是RotateSystem,继承自ComponentSystem,作用是做entity的行为驱动。

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用于遍历当前所有的entity,然后将数据赋值给entity进行操作;

编写代码完毕,就将第二个脚本RotateAuthoring挂载在Cube上。设置DegresPerSecond的值为50:

运行项目,cube开始旋转。查看status:

(3)使用JobSystem进行优化

修改RotateSystem.cs脚本:

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);
    }
}

主要变动是将继承改为了JobComponentSystem,增加了一个RotateJob,然后到OnUpdate中调用job;

(4)使用BurstCompile
在菜单栏中启用BurstCompile

在RotateSystem代码中的RotateJob结构体上添加[BurstCompile]特性,需要using 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)验证
开启SubScene的编辑,并大量复制cube,3000个以上。保存子场景。运行,开启unity编辑器的Status来查看:

我们发现,帧率依旧很稳定,只是Batches飙高到了3359。我们也需要优化掉:

(6)优化Batches

在Project面板下创建一个Material,命名为cube,并勾选Enable GPU Instancing.

选中子场景的所有cube,并将材质赋值到所有cube上。保存子场景,再次运行,发现batches已经获得了优化,帧率也大幅度提高。

小结

DOTS带来的性能改进是十分客观的,可以想象一些弹幕游戏、塔防游戏,使用上DOTS是可以非常直观的看到性能改进的。目前Unity也在大力推这套开发技术,相信未来会有越来越多的项目使用DOTS,并得益于DOTS.

Over~

转载请注明出处。

2020.2.9 优三帝同学 By Mark


博主公众号:优三帝

打赏
— 于 共写了3538个字
— 文内使用到的标签:

《“Unity DOTS简明教程”》 有 6 条评论

  1. wellall说道:

    干货十足!讲解到位。

  2. wellall说道:

    请求加上dots模式发布H5版本的操作流程,哈哈。

  3. 李家君说道:

    Entity.IJobForEach方法已经在2020.6.20过时了。。。

    • U3DC说道:

      对,DOTS一直在迭代,所以目前还在beta中,尝鲜可以,正式使用预计还要些时间吧…

  4. Zhidai说道:

    第三个脚本RotateSystem在VS里报错了,博主知道怎么修改吗,大概=&gt那里

    • U3DC说道:

      =&gt 这个改成 ” => ” lambda表达式,我这个页面编辑器自动把箭头转义为&gt了。。尴尬

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据