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
44
namespace HelloCube.GameObjectSync
{
public partial struct DirectoryInitSystem : ISystem
{
[BurstCompile]
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。注意此处的 DirectoryManagedclass 的,因为我们使用的是托管的数据。

接着又创建一个 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
42
namespace HelloCube.GameObjectSync
{
public partial struct RotatorInitSystem : ISystem
{
[BurstCompile]
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
30
namespace HelloCube.GameObjectSync
{
public partial struct RotationSystem : ISystem
{
[BurstCompile]
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;
}
}
}
}