I am trying to calculate and assign targets for entities in the game, but I couldn’t fix this error:
InvalidOperationException: The UNKNOWN_OBJECT_TYPE FindTargetBurstJob.JobData.TranslationTypeHandle has not been assigned or constructed. All containers must be valid when scheduling a job.
Unity.Entities.JobChunkExtensions.ScheduleInternal[T] (T& jobData, Unity.Entities.EntityQuery query, Unity.Jobs.JobHandle dependsOn, Unity.Jobs.LowLevel.Unsafe.ScheduleMode mode, System.Boolean isParallel)
Here is the code:
public class FindTargetJobSystem : SystemBase {
private struct EntityWithPosition
{
public Entity entity;
public float3 position;
}
private EntityQuery unitQuery;
private EntityQuery targetQuery;
private EndSimulationEntityCommandBufferSystem endSimulationEntityCommandBufferSystem;
protected override void OnCreate()
{
base.OnCreate();
endSimulationEntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
}
protected override void OnUpdate()
{
targetQuery = GetEntityQuery(typeof(Enemy), ComponentType.ReadOnly<Translation>());
NativeArray<Entity> targetEntityArray = targetQuery.ToEntityArray(Allocator.TempJob);
NativeArray<Translation> targetTranslationArray = targetQuery.ToComponentDataArray<Translation>(Allocator.TempJob);
NativeArray<EntityWithPosition> targetArray = new NativeArray<EntityWithPosition>(targetEntityArray.Length, Allocator.TempJob);
for (int i = 0; i < targetEntityArray.Length; i++) {
targetArray[i] = new EntityWithPosition {
entity = targetEntityArray[i],
position = targetTranslationArray[i].Value,
};
}
targetEntityArray.Dispose();
targetTranslationArray.Dispose();
unitQuery = GetEntityQuery(ComponentType.ReadOnly<Friend>(), ComponentType.ReadOnly<Translation>(), ComponentType.Exclude<HasTarget>());
NativeArray<Entity> closestTargetEntityArray = new NativeArray<Entity>(unitQuery.CalculateEntityCount(), Allocator.TempJob);
FindTargetBurstJob findTargetBurstJob = new FindTargetBurstJob()
{
targetArray = targetArray,
closestTargetEntityArray = closestTargetEntityArray
};
this.Dependency = findTargetBurstJob.ScheduleParallel(unitQuery, this.Dependency);
var entityCommandBuffer = endSimulationEntityCommandBufferSystem.CreateCommandBuffer().AsParallelWriter();
Entities
.WithStoreEntityQueryInField(ref unitQuery)
.ForEach((Entity entity,int entityInQueryIndex) =>
{
if (closestTargetEntityArray[entityInQueryIndex] != Entity.Null)
{
entityCommandBuffer.AddComponent(entityInQueryIndex, entity, new HasTarget { targetEntity = closestTargetEntityArray[entityInQueryIndex] });
}
}).ScheduleParallel();
this.Dependency = findTargetBurstJob.ScheduleParallel(unitQuery, this.Dependency);
endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(this.Dependency);
}
[BurstCompile]
private struct FindTargetBurstJob : IJobChunk
{
[DeallocateOnJobCompletion] [ReadOnly] public NativeArray<EntityWithPosition> targetArray;
public NativeArray<Entity> closestTargetEntityArray;
[ReadOnly] public ComponentTypeHandle<Translation> TranslationTypeHandle;
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
{
var translations = chunk.GetNativeArray(TranslationTypeHandle);
for (int i = 0; i < translations.Length; i++)
{
float3 unitPosition = translations[i].Value;
Entity closestTargetEntity = Entity.Null;
float3 closestTargetPosition = float3.zero;
for (int j = 0; j < targetArray.Length; j++)
{
EntityWithPosition targetEntityWithPosition = targetArray[j];
if (closestTargetEntity == Entity.Null)
{
closestTargetEntity = targetEntityWithPosition.entity;
closestTargetPosition = targetEntityWithPosition.position;
}
else
{
if (math.distance(unitPosition, targetEntityWithPosition.position) < math.distance(unitPosition, closestTargetPosition))
{
closestTargetEntity = targetEntityWithPosition.entity;
closestTargetPosition = targetEntityWithPosition.position;
}
}
}
closestTargetEntityArray[i] = closestTargetEntity;
}
}
}
}