I have the following setup:
-
BeginInitializationCommandBuffer - Destroys killed entities
-
TargetingSystem - Finds targets in range and puts them in a buffer
-
GetComponentsFromEntityTestSystem - Checks if targets exist
-
Other Systems - Attack and (possibly) destroy targets via BeginInitializationCommandBuffer
The third step however does sometimes throw an “Entity Entity(XXX:XXX) does not exist” error.
As there are no active command buffers between the TargetingSystem and the GetComponentsFromEntityTestSystem, it seems like the collisionWorld.CalculateDistance
returns entities that have already been destroyed.
Does this have anything to to with when the physics world is being built or updated?
I replaced the TargetingSystem with a system that does not use physics, which is obviously slower, but does not produce the same error.
public class PhysicsTargetingSystem : SystemBase
{
private BuildPhysicsWorld buildPhysicsWorld;
private EndFramePhysicsSystem endFramePhysicsSystem;
protected override void OnCreate()
{
this.buildPhysicsWorld = World.GetExistingSystem<BuildPhysicsWorld>();
this.endFramePhysicsSystem = World.GetExistingSystem<EndFramePhysicsSystem>();
}
protected override void OnUpdate()
{
var collisionWorld = this.buildPhysicsWorld.PhysicsWorld.CollisionWorld;
this.Dependency =
JobHandle.CombineDependencies(this.Dependency, this.endFramePhysicsSystem.GetOutputDependency());
Entities.ForEach(
(Entity entity, ref LocalToWorld trans, ref DynamicBuffer<Target> targets, in SphereTargeting sphereTargeting,
in CollisionInput collInput) =>
{
var hits = new NativeList<DistanceHit>(Allocator.Temp);
var filter = new CollisionFilter()
{
BelongsTo = (uint) collInput.BelongsTo,
CollidesWith = (uint) collInput.CollidesWith,
GroupIndex = 0
};
var distanceInput = new PointDistanceInput()
{
Position = trans.Position,
MaxDistance = sphereTargeting.Radius,
Filter = filter
};
collisionWorld.CalculateDistance(distanceInput, ref hits);
targets.Clear();
for (int i = 0; i < hits.Length; i++)
{
if (entity == hits[i].Entity) continue; //Ignore self
targets.Add(new Target()
{
Entity = hits[i].Entity,
});
}
hits.Dispose();
}).ScheduleParallel();
}
}
public class GetComponentsFromEntityTestSystem : SystemBase
{
protected override void OnUpdate()
{
var positions = GetComponentDataFromEntity<LocalToWorld>(true);
Entities
.WithReadOnly(positions)
.ForEach((
Entity entity,
ref DynamicBuffer<Target> targets,
in LocalToWorld localToWorld) =>
{
for (int i = 0; i < targets.Length; i++)
{
if(!positions.HasComponent(targets[i].Entity)) Debug.LogError($"Entity {targets[i].Entity} does not exist");
}
}).ScheduleParallel();
}
}