Skip to content

Instantly share code, notes, and snippets.

@mattdymott
Last active April 30, 2024 15:28
Show Gist options
  • Save mattdymott/556888e4c804d0b26ad60034942fa7ee to your computer and use it in GitHub Desktop.
Save mattdymott/556888e4c804d0b26ad60034942fa7ee to your computer and use it in GitHub Desktop.
Example of how to use ICollisionEventsJob from Unity.Physics
// CollisionResponse option on PhysicsShape must be set to CollideRaiseCollisionEvents.
[UpdateInGroup(typeof(PhysicsSystemGroup))]
[UpdateAfter(typeof(PhysicsSimulationGroup))]
public partial struct CalculateDetailsTest_PhysicsEventSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<SimulationSingleton>();
state.RequireForUpdate<PhysicsWorldSingleton>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var physicsWorldSingleton = SystemAPI.GetSingleton<PhysicsWorldSingleton>();
state.Dependency = new CollisionJob()
{
PhysicsWorldSingleton = physicsWorldSingleton
}.Schedule(SystemAPI.GetSingleton<SimulationSingleton>(), state.Dependency);
}
[BurstCompile]
private struct CollisionJob : ICollisionEventsJob
{
// Its important that this is marked as [ReadOnly], otherwise you will get errors.
[ReadOnly] public PhysicsWorldSingleton PhysicsWorldSingleton;
public void Execute(CollisionEvent collisionEvent)
{
var collisionDetails = collisionEvent.CalculateDetails(ref PhysicsWorldSingleton.PhysicsWorld);
var avgContactPointPosition = collisionDetails.AverageContactPointPosition;
Debug.Log($"A: {collisionEvent.EntityA}, B: {collisionEvent.EntityB}, {avgContactPointPosition}");
foreach(var contactPosition in collisionDetails.EstimatedContactPointPositions)
{
Debug.Log($"{contactPosition}");
}
}
}
}
[UpdateInGroup(typeof(PhysicsSystemGroup))]
[UpdateAfter(typeof(PhysicsSimulationGroup))]
public partial struct TestPhysicsEventSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<SimulationSingleton>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.Dependency = new CollisionJob().Schedule(
SystemAPI.GetSingleton<SimulationSingleton>(), state.Dependency);
}
[BurstCompile]
private struct CollisionJob : ICollisionEventsJob
{
public void Execute(CollisionEvent collisionEvent)
{
Debug.Log($"A: {collisionEvent.EntityA}, B: {collisionEvent.EntityB}");
}
}
}
public struct Touch : IComponentData
{}
public readonly struct Touched : IComponentData
{
public readonly Entity Who;
public readonly float3 Normal;
public Touched(Entity who, float3 normal)
{
Who = who;
Normal = normal;
}
}
[UpdateInGroup(typeof(PhysicsSystemGroup))]
[UpdateAfter(typeof(PhysicsSimulationGroup))]
public partial struct TouchSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<SimulationSingleton>();
state.RequireForUpdate<EndSimulationEntityCommandBufferSystem.Singleton>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.Dependency = new CollisionJob()
{
TouchLookup = SystemAPI.GetComponentLookup<Touch>(true),
VelocityLookup = SystemAPI.GetComponentLookup<PhysicsVelocity>(true),
CommandBuffer = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>()
.CreateCommandBuffer(state.WorldUnmanaged)
}.Schedule(SystemAPI.GetSingleton<SimulationSingleton>(), state.Dependency);
}
[BurstCompile]
private struct CollisionJob : ICollisionEventsJob
{
[ReadOnly] public ComponentLookup<Touch> TouchLookup;
[ReadOnly] public ComponentLookup<PhysicsVelocity> VelocityLookup;
public EntityCommandBuffer CommandBuffer;
private bool IsDynamic(Entity entity) => VelocityLookup.HasComponent(entity);
private bool IsTouchable(Entity entity) => TouchLookup.HasComponent(entity);
public void Execute(CollisionEvent collisionEvent)
{
var entityA = collisionEvent.EntityA;
var entityB = collisionEvent.EntityB;
if(IsTouchable(entityA) && IsDynamic(entityB))
{
CommandBuffer.AddComponent(entityA, new Touched(entityB, collisionEvent.Normal));
}
else
if(IsTouchable(entityB) && IsDynamic(entityA))
{
CommandBuffer.AddComponent(entityB, new Touched(entityA, collisionEvent.Normal));
}
}
}
}
@LeMetamax
Copy link

Awesome 😎
Thank you very much!
I had to pass in ref new PhysicsWorld() which worked for some reason. But I'll change it to your version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment