UnityECS学习06-ECS中Transform的各种用法
ECS 当中的 Transform
在 ECS 当中,主要含有 5 个 ECS Component,分别是:
LocalToWorld
:位置LocalTransform
:旋转PostTransformMatrix
:缩放Parent
,Child
:层级关系
其中,还有两个 System 来维护这些 Component:
ParentSystem
LocalToWorldSystem
LocalToWorld
表示从本地坐标到世界坐标的变换矩阵。这个矩阵是由内置的 LocalToWorldSystem
来维护的。一般只需要读取不需要改变其值。
LocalTransform
表示 entity 对其父 entity 的相对坐标,旋转和缩放,如果没有父 entity,则是相对于世界坐标。值得注意的是:其中的 Rotation
也就是旋转,是一个 float
值变量,也就是 LocalTransform 只能表示等比缩放(uniform scale)。因此需要 PostTransformMatrix
,来处理非等比缩放的情况。
Parent
用来设置 entity 父子关系,一个 entity 最多只能有一个 Parent
Child
entity 可以有不限数量个 Child,Child 的值也是由内置的 ParentSystem
来维护的。
Reparenting
首先在我们的 SubScene 当中直接右键点击 RotationCube
添加一个新的 Cube
,新添加的无需挂载任何脚本。接着我们再添加如下两个脚本即可观察到:RotationCube
一直在旋转,Cube
转一会儿停一会儿。
1 | // RotationSystem.cs |
第一个脚本不解释,就是最开始例子里面的旋转方法。
1 | // ReparentingSystem.cs |
这就是我们的 Reparenting 脚本,注意此处有一点和官方不一样的是在 OnCreate
当中 attched
初始化为了 false
。此处逻辑与官方示例则相反。此处先说明一下是为什么,因为我是自己创建子对象复现的,但是在创建的时候,并不会根据 UnityEditor 的 gameobject 关系自动添加 Child
, Parent
相关的组件,并且我试过在 bake
的时候也不会。所以我们最开始的状态就应当为 attched = false
。我后面又看了看官方文档的场景和代码,发现其的 RotationCube
最开始了带了 Child
的组件(此处我不知道是怎么回事,因此提了个 issue,坐等其他佬回复了),因此官方示例使用 attched = true
是完全正确的。
好了,再来看一看这个代码,首先有三个成员变量:
attached
:表明两个 gameobject 之间是否有 父子关系timer
:简单的计时器interval
:单次 旋转/暂停 时间间隔
- 在每次计时器时间到了的时候,都使用
SystemAPI.GetSingletonEntity<RotationSpeed>()
获取我们场景中唯一挂载了RotationSpeed
的RotationCube
。 - 接着使用
new EntityCommandBuffer(Allocator.Temp)
创建了一个临时的实体命令缓冲区 - 如果两者具有父子关系,则首先获取
RotationCube
实体上的Child
动态缓冲区,然后移除其中每一个 entity 的Parent
组件。如果两者没有,对于每个不具有RotationSpeed
组件的实体,添加一个Parent
组件(其值就是RotationCube
实体) - 最后使用
ecb.Playback(state.EntityManager);
执行缓冲区的更改,并且反转attached
的状态。