GameObjectSync
首先在主场景中添加 Toggle
和一个空物体 Directory
。将后者挂上脚本:
1 2 3 4 5 6 7 8 9 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
。注意此处的 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 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; } } } }