Unity DOTS中的baking(五)prefabs
在DOTS的baking过程中,prefabs会被烘焙成entity prefabs。entity prefabs也是一个entity,可以在运行时实例化,就像是prefab一样。我们可以使用EntityPrefabReference
这个struct,将prefab注册到baker中。
首先,我们需要定义一个包含EntityPrefabReference
的ECS component:
public struct Config : IComponentData
{
public EntityPrefabReference PrefabReference;
}
然后,再定义一个authoring component,用来给entity添加Config这个component:
public class ConfigAuthoring : MonoBehaviour
{
public GameObject Prefab;
class Baker : Baker<ConfigAuthoring>
{
public override void Bake(ConfigAuthoring authoring)
{
var prefabEntity = new EntityPrefabReference(authoring.Prefab);
var entity = GetEntity(TransformUsageFlags.None);
AddComponent(entity, new Config
{
PrefabReference = prefabEntity,
});
}
}
}
此时我们使用传入的prefab新建了一个EntityPrefabReference
类型的对象。自此,prefab的baking过程就结束了。接下来,就是要如何加载这个entity prefab了。
要加载 EntityPrefabReference
引用的prefab,还需要将 RequestEntityPrefabLoaded
这个component添加到entity中。当prefab加载结束时,Unity会将PrefabLoadResult
这个component添加到包含RequestEntityPrefabLoaded
的同一entity中。我们可以在统一的一个system中完成这项工作:
public partial struct LoadPrefabSystem : ISystem
{
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<Config>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.Enabled = false;
var config = SystemAPI.GetSingleton<Config>();
var configEntity = SystemAPI.GetSingletonEntity<Config>();
state.EntityManager.AddComponentData(configEntity, new RequestEntityPrefabLoaded
{
Prefab = config.PrefabReference
});
}
}
最后,在使用这个prefab的system中,只有当获取到PrefabLoadResult
这个component时,system才会执行:
public partial struct SpawnSystem : ISystem
{
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<Config>();
state.RequireForUpdate<PrefabLoadResult>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var config = SystemAPI.GetSingleton<Config>();
var configEntity = SystemAPI.GetSingletonEntity<Config>();
if (!SystemAPI.HasComponent<PrefabLoadResult>(configEntity))
{
return;
}
var prefabLoadResult = SystemAPI.GetComponent<PrefabLoadResult>(configEntity);
var entity = state.EntityManager.Instantiate(prefabLoadResult.PrefabRoot);
var random = Random.CreateFromIndex((uint) state.GlobalSys