Hi again, I’m hoping someone could help me figure out what’s going wrong here. So I am trying to read data from an ICollisionEventsJob, but for some reason it is not adding any collision data to my NativeList. I’m not sure if this is because the Execute() function is not being called or if it’s happening for some other reason. I have objects that are visibly colliding in my scene.
using System;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics.Systems;
using UnityEngine;
using UnityEngine.Assertions;
namespace Unity.Physics.Tests
{
[UpdateBefore(typeof(StepPhysicsWorld))]
public class CollisionSystem : JobComponentSystem
{
BuildPhysicsWorld m_BuildPhysicsWorldSystem;
StepPhysicsWorld m_StepPhysicsWorldSystem;
NativeList<CollisionDetails> collisionDetails = new NativeList<CollisionDetails>(1, Allocator.Persistent);
protected override void OnCreate()
{
m_StepPhysicsWorldSystem = World.GetOrCreateSystem<StepPhysicsWorld>();
m_BuildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>();
}
public struct CollisionJob : ICollisionEventsJob
{
private bool m_Initialized;
[ReadOnly]
public PhysicsWorld World;
public NativeList<CollisionDetails> CollisionDetails;
public void Execute(CollisionEvent collisionEvent)
{
if (!m_Initialized)
{
CollisionDetails.Clear();
m_Initialized = true;
}
Entity entityA = collisionEvent.Entities.EntityA;
Entity entityB = collisionEvent.Entities.EntityB;
CollisionEvent.Details collisionEventDetails = collisionEvent.CalculateDetails(ref World);
CollisionDetails collisionDetails = new CollisionDetails
{
ImpulseMagnitude = collisionEventDetails.EstimatedImpulse,
ImpulseDirection = collisionEvent.Normal,
ImpulsePoint = collisionEventDetails.AverageContactPointPosition
};
CollisionDetails.Add(collisionDetails);
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
m_BuildPhysicsWorldSystem.FinalJobHandle.Complete();
SimulationCallbacks.Callback testCollisionEventCallback = (ref ISimulation simulation, ref PhysicsWorld world, JobHandle inDeps) =>
{
var job = new CollisionJob
{
World = m_BuildPhysicsWorldSystem.PhysicsWorld,
CollisionDetails = collisionDetails,
}.Schedule(simulation, ref world, inDeps);
job.Complete();
foreach (CollisionDetails details in collisionDetails)
{
Debug.Log(details.ImpulseMagnitude);
}
return job;
};
m_StepPhysicsWorldSystem.EnqueueCallback(SimulationCallbacks.Phase.PostSolveJacobians, testCollisionEventCallback, inputDeps);
return inputDeps;
}
protected override void OnDestroy()
{
collisionDetails.Dispose();
}
public struct CollisionDetails
{
public float ImpulseMagnitude;
public float3 ImpulseDirection;
public float3 ImpulsePoint;
}
}
}
Yes, indeed! That was the problem. I thought that SpeedComponentData[entityA] is an actual reference to the component and that setting the value will affect it.
I have similar issue I have system with ICollisonEventsJob and ITriggerEventsJob. None of them gets called.
I have set Collision Response to collide Raise Collision Event. Something ale I am missing? Is there any visual debugger for DOTS physics?
using Components;
using Unity.Entities;
using Unity.Jobs;
using Unity.Physics;
using Unity.Physics.Systems;
namespace Systems
{
[UpdateAfter(typeof(EndFramePhysicsSystem))]
public class CollisionSystem : SystemBase
{
private BuildPhysicsWorld _PhysicsWorld;
private ISimulation _Simulation;
protected override void OnCreate()
{
base.OnCreate();
_PhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();;
_Simulation = World.GetOrCreateSystem<StepPhysicsWorld>().Simulation;
}
protected override void OnUpdate()
{
Entities.ForEach((DynamicBuffer<CollisionBuffer> collisionBuffer) => collisionBuffer.Clear()).Run();
Entities.ForEach((DynamicBuffer<TriggerBuffer> collisionBuffer) => collisionBuffer.Clear()).Run();
var collisionJob = new CollisionJob
{
Collisions = GetBufferFromEntity<CollisionBuffer>()
};
var triggerJob = new TriggerJob
{
Collisions = GetBufferFromEntity<TriggerBuffer>()
};
var collisionHandle = collisionJob.Schedule(_Simulation, ref _PhysicsWorld.PhysicsWorld, Dependency);
var triggerHandle = triggerJob.Schedule(_Simulation, ref _PhysicsWorld.PhysicsWorld, Dependency);
JobHandle.CombineDependencies(collisionHandle,triggerHandle).Complete();
}
private struct CollisionJob : ICollisionEventsJob
{
public BufferFromEntity<CollisionBuffer> Collisions;
public void Execute(CollisionEvent collisionEvent)
{
if (Collisions.Exists(collisionEvent.EntityA))
Collisions[collisionEvent.EntityA].Add(new CollisionBuffer {Entity = collisionEvent.EntityB});
if (Collisions.Exists(collisionEvent.EntityB))
Collisions[collisionEvent.EntityB].Add(new CollisionBuffer {Entity = collisionEvent.EntityA});
}
}
private struct TriggerJob : ITriggerEventsJob
{
public BufferFromEntity<TriggerBuffer> Collisions;
public void Execute(TriggerEvent collisionEvent)
{
if (Collisions.Exists(collisionEvent.EntityA))
Collisions[collisionEvent.EntityA].Add(new TriggerBuffer {Entity = collisionEvent.EntityB});
if (Collisions.Exists(collisionEvent.EntityB))
Collisions[collisionEvent.EntityB].Add(new TriggerBuffer {Entity = collisionEvent.EntityA});
}
}
}
}
Are you seeing collisions between bodies that should raise collision events? At least one of them should have CollideRaiseCollisionEvents. Also for triggers, use RaiseTriggerEvents.
What you are trying to do looks like something already provided in the samples, DynamicBufferCollisionEventAuthoring and DynamicBufferTriggerEventAuthoring, you might want to take a look at that. In the samples, 2d1. Triggers and 2d2. Collision Events.
Thanks for a replay, I will look into those samples. I see collisions on of those bodies is a player and other are walls and enemies. Collisions work as they should.
You are right I am trying to do something similar to code in the samples, not that sophisticated.
I know why my events did not get triggered. In line 20 I get a ISimulation from StepPhysicsWorld and then I use it in lines 37 and 38. Where I should obtain ISimulation from StepPhysicsWolrd every time I schedule a job. Maybe someone will make the same mistake as I and it will save ones time.