Last active
April 30, 2024 15:28
-
-
Save mattdymott/556888e4c804d0b26ad60034942fa7ee to your computer and use it in GitHub Desktop.
Example of how to use ICollisionEventsJob from Unity.Physics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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}"); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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}"); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | |
} | |
} | |
} | |
} |
Thank you so much! This is super helpful..
This example save my life 😁 Thank you so much !
Any ideas how to get the contact point? Using monobehavior it would be something like collision.GetContact(0).point.... or collider.ClosestPoint(vector).
I saw a hint suggesting to use AverageContactPointPosition in collisionEvent.CalculateDetails.... but I don't know how to reference Physics World without getting console errors
added new example to do this.
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
Even better is the version tertle provides (https://github.com/tertle/com.bovinelabs.core) under PhysicsStates