Unity DOTS: Referencing Types with Burst
Summary
Because Type
and typeof()
are managed code, which can’t be compiled with Burst, we need to use static function ComponentType.ReadWrite<T>()
instead.
Environment
- Unity 2019.4.0f1
- Entities 0.11.1-preview.4
- Burst 1.3.0-preview.12
Explanation
Assuming we need to check if the entity has a particular component through the array from EntityManager.GetComponentTypes()
. By looking at the constructor of ComponentType
, there is only one version with a Type
parameter, so just give it a try:
public struct SampleComponent : IComponentData { }
[AlwaysSynchronizeSystem]
public class SampleSystem : JobComponentSystem
{
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
EntityManager entityManager = EntityManager;
Entities.ForEach((Entity entity) =>
{
NativeArray<ComponentType> types = entityManager.GetComponentTypes(entity, Allocator.TempJob);
if (types.Contains(new ComponentType(typeof(SampleComponent))))
{
Debug.Log("Found SampleComponent!");
}
types.Dispose();
}).Run();
return default;
}
}
However, the Burst compiler complains when compiling after hitting play:
D:\Workspace\ecs\Assets\Scripts\SampleSystem.cs(15,13): Burst error BC1025: Accessing the type `SampleComponent` (e.g. using `typeof`) is not supported
Because both Type
and typeof()
are managed code, it’s not allowed by the Burst compiler.
Fortunately, there is a static function ComponentType.ReadWrite<T>()
. Let’s replace new ComponentType(typeof(SampleComponent))
with it:
[AlwaysSynchronizeSystem]
public class SampleSystem : JobComponentSystem
{
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
EntityManager entityManager = EntityManager;
Entities.ForEach((Entity entity) =>
{
NativeArray<ComponentType> types = entityManager.GetComponentTypes(entity, Allocator.TempJob);
if (types.Contains(ComponentType.ReadWrite<SampleComponent>()))
{
Debug.Log("Found SampleComponent!");
}
types.Dispose();
}).Run();
return default;
}
}
Actually, you can use ComponentType.ReadOnly<T>()
if you like, and there is no difference between them, since the implementation of IEquatable<T>.Equals()
in ComponentType
only compares TypeIndex
:
public bool Equals(ComponentType other)
{
return TypeIndex == other.TypeIndex;
}
Taking a look at the implementation of ComponentType.ReadWrite<T>()
, we can see that it’s done through TypeManager
, which registers all the component types during the initialization:
public static ComponentType ReadWrite<T>()
{
return FromTypeIndex(TypeManager.GetTypeIndex<T>());
}
So it seems a good practice to reference component types by cache the type index by TypeManager.GetTypeIndex<T>()
.
Leave a Comment