UnityECS学习08-GameObjectSync
GameObjectSync
首先在主场景中添加 Toggle
和一个空物体 Directory
。将后者挂上脚本:1
2
3
4
5
6
7
8
9// Directory.cs
namespace HelloCube.GameObjectSync
{
public class Directory : MonoBehaviour
{
public GameObject RotatorPrefab;
public Toggle RotationToggle;
}
}
挂载后将我们的预制体和 Toggle
都拖入。
接下来创建 DirectoryInitSystem.cs
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44namespace HelloCube.GameObjectSync
{
public partial struct DirectoryInitSystem : ISystem
{
[ ]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<Execute.GameObjectSync>();
}
public void OnUpdate(ref SystemState state)
{
state.Enabled = false;
var go = GameObject.Find("Directory");
if (go == null)
{
throw new Exception("GameObject 'Directory' not found");
}
var directory = go.GetComponent<Directory>();
var directoryManaged = new DirectoryManaged
{
RotatorPrefab = directory.RotatorPrefab,
RotationToggle = directory.RotationToggle
};
var entity = state.EntityManager.CreateEntity();
state.EntityManager.AddComponentData(entity, directoryManaged);
}
}
public class DirectoryManaged : IComponentData
{
public GameObject RotatorPrefab;
public Toggle RotationToggle;
public DirectoryManaged()
{
}
}
}
- 首先将
state.Enable
设置为false
,调用一次之后就关闭,防止多次创建cube
。 - 接着就是获取到场景中的
Directory
物体,从其身上的脚本拿到我们的预制体和Toggle
。注意此处的DirectoryManaged
是class
的,因为我们使用的是托管的数据。
接着又创建一个 RotatorInitSystem.cs
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42namespace HelloCube.GameObjectSync
{
public partial struct RotatorInitSystem : ISystem
{
[ ]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<Execute.GameObjectSync>();
state.RequireForUpdate<DirectoryManaged>();
}
public void OnUpdate(ref SystemState state)
{
var directory = SystemAPI.ManagedAPI.GetSingleton<DirectoryManaged>();
var ecb = new EntityCommandBuffer(Allocator.Temp);
foreach (var (rotationSpeed, entity) in SystemAPI.Query<RotationSpeed>().WithNone<RotatorGO>()
.WithEntityAccess())
{
var go = GameObject.Instantiate(directory.RotatorPrefab);
ecb.AddComponent(entity, new RotatorGO(go));
}
ecb.Playback(state.EntityManager);
}
}
public class RotatorGO : IComponentData
{
public GameObject Value;
public RotatorGO(GameObject value)
{
Value = value;
}
public RotatorGO()
{
}
}
}
- 查询
subscene
中存在RotationSpeed
并且没有RotatorGO
也就是无prefab
实体的 entity,Query
只能得到Component
加上WithEntityAccess()
可以访问对应的 entity。
接着在 RotationSystem.cs
中做类似于第一次的查询,只需在 OnUpdate
中修改了旋转如何赋值回给 RotatorGO
中的 GameObject 即可1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30namespace HelloCube.GameObjectSync
{
public partial struct RotationSystem : ISystem
{
[ ]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<Execute.GameObjectSync>();
state.RequireForUpdate<DirectoryManaged>();
}
public void OnUpdate(ref SystemState state)
{
var directory = SystemAPI.ManagedAPI.GetSingleton<DirectoryManaged>();
if (!directory.RotationToggle.isOn)
{
return;
}
float deltaTime = SystemAPI.Time.DeltaTime;
foreach (var (transform, speed, go) in SystemAPI
.Query<RefRW<LocalTransform>, RefRO<RotationSpeed>, RotatorGO>())
{
transform.ValueRW = transform.ValueRO.RotateY(speed.ValueRO.RadiansPerSecond * deltaTime);
go.Value.transform.rotation = transform.ValueRO.Rotation;
}
}
}
}