DOTS1.0使用:E、C、S创建
DOTS1.0发布了,记录一下它的简单使用。
笔记基于:Unity DOTS 1.0 in 60 MINUTES! - YouTube、Spawner example | Entities | 1.0.0-pre.44 (unity3d.com)
相关链接:Unity ECS 1.0 Full Project Tutorial | Step-by-Step 🧟♂️ - YouTube
官方的例子:Unity-Technologies/EntityComponentSystemSamples (github.com)
准备
Unity需要2022版本,新建一个3D URP项目,打开Package Manager窗口,点击左上角的加号,再点击“add package by name”,输入“com.unity.entities”回车,等待Unity自动安装。在写此笔记时,DOTS虽然已经是1.0,但还是preview(记住打开Package Manager的允许预览包)。所有的依赖也会安装。
再次重复步骤,输入“com.unity.entities.graphics”,安装基于DOTS的图形包,这个包能够基于DOTS渲染Mesh,并且支持实例化网格渲染和LOD。
Entities使用微软的源生成器来生成代码,所以需要使用Visual Studio 2022或者Rider2021.3.3以上版本。
在Project Settings——Editor窗口,找到“Enter Play Mode Settings”,勾选“Enter Play Mode Options”,但是不要勾选“Reload Domain”和“Reload Scene”。这会关闭Unity的“域重载”,但是关闭“域重载”后静态变量和静态事件函数不会重置,有关解决方法请参考:Unity Domain Reoad
创建Entities
创建SubScene
在Hierarchy面板右键——New SubScene——Empty Scene,在弹出的窗口中输入场景名并保存。
SubScene的作用就是将在其内部创建的GameObject转化为Entities。
创建SubScene的GameObject
点击选中刚刚创建的SubScene,右键——GameObject——Create Empty,使用它的默认名字“GameObject”。
选中这个GameObject,在它的Inspector右上角有一个小圆圈,点击小圆圈,会弹出几种Entity的查看方式,我们选择Runtime,这种方式会显示此Entity包含的所有信息。
选中“GameObject”,右键——3D Object——Capsule。选中Capsule,删除它的Capsule Collider。
点击Window——Entities——Entities Hierarchy,这个Hierarchy可以显示用于ECS的所有项目。它的右上角也有小圆圈,点击切换为Runtime,然后在这个窗口中点击所有Entities项目,都是直接转换为Runtime模式。
创建Component
在Project窗口中新建Scripts文件夹,在其中创建一个脚本命名为“Speed”。
1 | using Unity.Entities; |
Component作为数据容器,需要与Entity联系,还需要一定的方法和GameObject联系,用来方便地设置各种数据。
再新建一个脚本,命名为“SpeedAuthoring”
1 | using UnityEngine; |
Unity Entities提供了Baker类,用于将GameObject数据转化为ECS使用的ComponentData。
将“SpeedAuthoring”挂载到我们之前在EntitySubScene创建的GameObject,随便设置个数字。并打开Runtime
可以看到Speed数值已经顺利转化。
创建System
SystemBase和ISystem
System | 区别 |
---|---|
SystemBase | 1. Class-Managed 2. 只能在主线程运行 3. 不能使用Burst编译器 |
ISystem | 1. Struce-Unmanaged 2.可以使用Burst编译器 3. 多线程 |
一些非常基础的代码,或者只希望在主线程运行的代码,可以使用SystemBase
为了更高的性能,使用ISystem
使用SystemBase
在Scripts文件夹内新建脚本,命名为“MovingSystemBase”
1 | using Unity.Entities; |
继承SystemBase必须使用partial关键字,用来优化DOTS的编译
如果我们想使用System移动物体,就需要这个物体Entity对应的World Transform、Local Transform等默认的Component
为了简化Component操作,Unity在DOTS1.0提出了Aspect概念:
Aspect overview | Entities | 1.0.0-pre.15 (unity3d.com)
Aspect是一个类似Object的包装器,您可以使用它将实体组件的子集组合到一个C#结构中。Aspect对于组织Component代码和简化系统中的Query非常有用。Aspect也能添加一些函数。
默认的Transform Aspect可以将具有父对象的Entity的相对于父级的坐标和相对于世界的坐标同步。更方便地移动entity。
我们修改“MovingSystemBase”脚本:
1 | using Unity.Entities; |
在C# JobSystem里面,Run表示在主线程运行,Schedule表示在一个工作线程中运行,ScheduleParallel表示在多个工作线程中运行
使用Entities.ForEach来查询有一定的缺点,就是不能嵌套轮询。而使用foreach可以
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
public partial class MovingSystemBase : SystemBase
{
protected override void OnUpdate()
{
foreach (var transformAspect in SystemAPI.Query<TransformAspect>())
{
foreach(var speed in SystemAPI.Query<Speed>()){
}
transformAspect.LocalPosition += new float3(SystemAPI.Time.DeltaTime, 0, 0);
}
}
}
这时我们进入运行模式,会看到所有的Entities会移动。这时我们打开WIndows——Entities——Systems,在Update——Simulation System Group中可以看到我们的Moving System Base
点击左侧的“小插头”图标,会停止这个System的功能