EntityComponentSystemSamples
EntityComponentSystemSamples copied to clipboard
Physics stateful events inconsistency when both objects have physics body.
I found out that in case if both interacting objects have colliders and only one body has physics shape everything goes fine and trigger events are correct, but in case if both have rigidbodies at the same time instead the behaviour is chaotic.
Example
using Unity.Entities;
using Unity.Physics.Stateful;
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[UpdateAfter(typeof(StatefulTriggerEventBufferSystem))]
public partial class PickupRangeSystem : SystemBase {
private BeginFixedStepSimulationEntityCommandBufferSystem _ecbBeginSystem;
private EndFixedStepSimulationEntityCommandBufferSystem _ecbEndSystem;
protected override void OnCreate() {
base.OnCreate();
_ecbBeginSystem = World.GetOrCreateSystem<BeginFixedStepSimulationEntityCommandBufferSystem>();
_ecbEndSystem = World.GetOrCreateSystem<EndFixedStepSimulationEntityCommandBufferSystem>();
}
protected override void OnUpdate() {
var ecbBegin = _ecbBeginSystem.CreateCommandBuffer().AsParallelWriter();
var ecbEnd = _ecbEndSystem.CreateCommandBuffer().AsParallelWriter();
Dependency = Entities
.WithAll<Player>()
.ForEach((Entity entity, int entityInQueryIndex, in DynamicBuffer<StatefulTriggerEvent> triggerEvents) => {
foreach (var triggerEvent in triggerEvents) {
if (!triggerEvent.TryGetOther(entity, out var other)) {
continue;
}
if (triggerEvent.State == StatefulEventState.Enter) {
ecbBegin.AddComponent(entityInQueryIndex, other.Entity, new PickupRangeEvent { State = PickupRangeState.Enter });
} else if (triggerEvent.State == StatefulEventState.Exit) {
ecbBegin.AddComponent(entityInQueryIndex, other.Entity, new PickupRangeEvent { State = PickupRangeState.Exit });
}
}
}).ScheduleParallel(Dependency);
Dependency = Entities
.WithAll<PickupRangeEvent>()
.ForEach((Entity entity, int entityInQueryIndex) => ecbEnd.RemoveComponent<PickupRangeEvent>(entityInQueryIndex, entity))
.ScheduleParallel(Dependency);
_ecbBeginSystem.AddJobHandleForProducer(Dependency);
_ecbEndSystem.AddJobHandleForProducer(Dependency);
}
}
In this example I'm using TryGetOther
method i added to StatefulTriggerEvent
for my convinience
public bool TryGetOther(in Entity entity, out (Entity Entity, int BodyIndex, ColliderKey ColliderKey) other) {
if (EntityA.CompareTo(entity) != 0 && EntityB.CompareTo(entity) != 0) {
other = (Entity.Null, -1, ColliderKey.Empty);
return false;
}
other = EntityA.CompareTo(entity) == 0
? (EntityB, BodyIndexB, ColliderKeyB)
: (EntityA, BodyIndexA, ColliderKeyA);
return true;
}
After running PickupViewSystem
I'm continuously getting Enter
and Exit
events while bodies are colliding.
using Unity.Entities;
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
public partial class PickupViewSystem : SystemBase {
protected override void OnUpdate() {
Entities
.WithoutBurst()
.WithAll<Pickup>()
.ForEach((in PickupRangeEvent pickupRangeEvent) => {
UnityEngine.Debug.Log(pickupRangeEvent.State);
}).Run();
}
}
Haven't tested for StatefulCollisionEvent
but i assume and it's quite obvious the issue exists for both.