I’m working on a simple ignore collision system. I trimmed down the ModidyContactJacobians sample, instead using a component containing an entity to ignore but the general idea is the same.
As soon as the two colliders are no longer intersecting I want to unignore the pair, but Im not quite sure how to do it, this is what I have currently:
var colliderLookup = GetComponentDataFromEntity<PhysicsCollider>(true);
var localToWorldData = GetComponentDataFromEntity<LocalToWorld>(true);
Entities
.WithBurst()
.WithReadOnly(colliderLookup)
.WithReadOnly(localToWorldData)
.ForEach((Entity entity, PhysicsCollider collider, ref IgnoreCollision ignore) =>
{
if (ignore.Entity == Entity.Null)
{
Debug.Log("returning");
return;
}
var other = colliderLookup[ignore.Entity];
var intersects = collider.Value.Value.CalculateDistance(new ColliderDistanceInput
{
Collider = other.ColliderPtr,
MaxDistance = 10,
Transform = new RigidTransform(math.mul(
math.inverse(localToWorldData[entity].Value),
localToWorldData[ignore.Entity].Value
))
});
if (!intersects)
{
Debug.Log("unignoring");
ignore.Entity = Entity.Null;
}
else
{
Debug.Log("still intersecting");
}
})
.Schedule();
Am I on the right track? I get an exception from Distance.ColliderCollider:
case CollisionType.Composite:
case CollisionType.Terrain:
// no support for composite query shapes
SafetyChecks.ThrowNotImplementedException();
EDIT: I’m guessing the problem is the gameobject hierarchy used for conversion has two colliders (one used as a trigger) and I should find the correct leaf before calculating the distance:
GetLeaf(ColliderKey key, out ChildCollider leaf)
Im not sure how to get the key though.
Here’s the full code
code
using Unity.Burst;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics;
using Unity.Physics.Systems;
using Unity.Transforms;
using UnityEngine;
unsafe class ClearIgnoreCollisionSystem : SystemBase
{
protected override void OnUpdate()
{
var colliderLookup = GetComponentDataFromEntity<PhysicsCollider>(true);
var localToWorldData = GetComponentDataFromEntity<LocalToWorld>(true);
Entities
.WithBurst()
.WithReadOnly(colliderLookup)
.WithReadOnly(localToWorldData)
.ForEach((Entity entity, PhysicsCollider collider, ref IgnoreCollision ignore) =>
{
if (ignore.Entity == Entity.Null)
{
Debug.Log("returning");
return;
}
var other = colliderLookup[ignore.Entity];
var intersects = collider.Value.Value.CalculateDistance(new ColliderDistanceInput
{
Collider = other.ColliderPtr,
MaxDistance = 10,
Transform = new RigidTransform(math.mul(
math.inverse(localToWorldData[entity].Value),
localToWorldData[ignore.Entity].Value
))
});
if (!intersects)
{
Debug.Log("unignoring");
ignore.Entity = Entity.Null;
}
else
{
Debug.Log("still intersecting");
}
})
.Schedule();
}
}
public struct IgnoreCollision : IComponentData
{
public Entity Entity;
public IgnoreCollision(Entity entity)
{
Entity = entity;
}
}
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[UpdateBefore(typeof(StepPhysicsWorld))]
public class IgnoreCollisionSystem : SystemBase
{
StepPhysicsWorld _stepPhysicsWorld;
SimulationCallbacks.Callback _jacobianModificationCallback;
protected override void OnCreate()
{
_stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
_jacobianModificationCallback = (ref ISimulation simulation, ref PhysicsWorld world, JobHandle inDeps) => new ModifyJacobiansJob
{
Ignored = GetComponentDataFromEntity<IgnoreCollision>(true)
}
.Schedule(simulation, ref world, inDeps);
RequireForUpdate(GetEntityQuery(new EntityQueryDesc
{
All = new ComponentType[] {typeof(IgnoreCollision)}
}));
}
protected override void OnUpdate()
{
if (_stepPhysicsWorld.Simulation.Type == SimulationType.NoPhysics)
return;
_stepPhysicsWorld.EnqueueCallback(SimulationCallbacks.Phase.PostCreateContactJacobians, _jacobianModificationCallback, Dependency);
}
[BurstCompile]
struct ModifyJacobiansJob : IJacobiansJob
{
[ReadOnly]
public ComponentDataFromEntity<IgnoreCollision> Ignored;
// triggers
public void Execute(ref ModifiableJacobianHeader h, ref ModifiableTriggerJacobian j)
{
}
public void Execute(ref ModifiableJacobianHeader jacHeader, ref ModifiableContactJacobian contactJacobian)
{
var entityA = jacHeader.EntityA;
var entityB = jacHeader.EntityB;
if (Ignored.HasComponent(entityA) && Ignored[entityA].Entity == entityB ||
Ignored.HasComponent(entityB) && Ignored[entityB].Entity == entityA)
{
jacHeader.Flags |= JacobianFlags.Disabled;
}
}
}
}