ECS Unity.Physics: Contacts, The Right Way (full OnCollisionEnter(Collision) analogue)


!! WIP -- Still writing this one !!

<-PREV | NEXT->

First I need to disable my old code.  Annotated my `StickyCollisionSystem` with `[DisableAutoCreation]`.  Scrap that -- decided to add this functionality to my existing system.

So the order of the physics phases affects when one can get which data.  You allegedly have to be in `PostCreateContacts` to get them but the doc also mentions you can get them from  `Simulation.Contacts`.  Let's find that.

`Library\PackageCache\com.unity.physics@0.1.0-preview\Unity.Physics\Dynamics\Simulation\Simulation.cs` is the `Simulation` implementation.

Ah the callback comes from that file, line 106 (for Unity.Physics preview-0.1.0).

The only `Contacts` I find in there is now in a `struct Context` which is placed in `internal m_Context` and passed by reference to various phases to populate etc including `ScheduleBuildContactJacobiansJobs()` which calls `Dispose()` on it anyway (so it won't be available later).

So, we definitely want to get this contact-gathering job working.

The physics jobs are scheduled in `StepPhysicsWorld.OnUpdate()` after `BuildPhysicsWorld` and before `ExportPhysicsWorld` and it gets the job handles for all of them in `public FinalSimulationJobHandle` and `public FinalJobHandle` !

Potentials:

  • TODO: Could I depend on `StepPhysicsWorld.FinalSimulationJobHandle` or `.FinalJobHandle`  to ensure my jobs have the info they need?
  • TODO: Could I tweak/split the scheduling of the rest of my job so I can access the data and `Dispose()` of my `TempJob` allocations appropriately?  Do I even need to?  Could I somehow swap to `Temp` allocations?
  • TODO: Do I actually still need my `ICollisionEventsJob` if I get contacts?  What's the difference?
    Restricted results down from thousands to just those with my Component `StickCause`.  The `ModifiableContactHeader` has the entities so indexed them into a `ComponentDataFromEntity<StickCause>` with `Exists()` = works.  Contact points don't exactly match my calculated ones but I'm not yet sure what the `ContactPoint.Distance` means so maybe that accounts for the variance?

(Pause for family afternoon.)

Realised my vision of when each of these things (my jobs, callbacks, systems, etc) run relative to each other is a bit wobbly so decided to diagram.  Much clearer!

Realised I need to restructure my jobs and need a new system to schedule completion (tidy-up my allocations).  It's also much neater to schedule all of my jobs from within the Physics callback.   Tried this but failed to account for certain storage inter-dependencies.   Managed to get a version that 100% works via a lucky hack involving the jobs scheduled in the callback happening a frame later.

Currently my system runs `[UpdateAfter(typeof(StepPhysicsWorld))]` so the `stepPhysicsWorld.EnqueueCallback(SimulationCallbacks.Phase.PostCreateContacts, onPostCreateContacts, outerInDeps)` is happening a frame later (below, the callback at line 5 in frame 200 was scheduled on line 1 in frame 199 then line 6 uses its results):

  1. 199:1: UGS.StickyCollisionSystem.OnUpdate()
  2. 199:1: UGS.StickyCollisionSystem.tidyUp()
  3. 199:1: UGS.StickyCollisionSystem.tidyUpActual()
  4. 199:1: UGS.StickyCollisionSystem.allocate()
  5. 200:1: UGS.StickyCollisionSystem.onPostCreateContacts()
  6. 200:1: UGS.StickyCollisionSystem.OnUpdate()
  7. 200:1: UGS.StickyCollisionSystem.tidyUp()
  8. 200:1: UGS.StickyCollisionSystem.tidyUpActual()
  9. 200:1: UGS.StickyCollisionSystem.allocate()
  10. 201:1: UGS.StickyCollisionSystem.onPostCreateContacts()

Instead I should have 2 systems:

  1. UpdateBefore(typeof(StepPhysicsWorld)) that schedules the callback.  The callback records the job handle.
  2. UpdateAfter(typeof(StepPhysicsWorld)) that does the rest of the work currently done and uses the job handle from before.


TODO: Resultant code diagram.

Aside: TODO: Am I reading this right?  It looks like `ICollisionEventJobExtensions.CollisionEventJobProcess.Execute()` is a preliminary implementation since it does set-up for batched parallel execution of our `ICollisionEventsJob` implementations but actually executes them in a simply `foreach` atm.  Similar code that processes `IContactsJob` in `IContactsJobExtensions.ContactsJobProcess.Execute()` does a lot more work relating to the `JobRanges` and `jobIndex`.

!! WIP -- Still writing this one !!

<-PREV | NEXT->

Leave a comment

Log in with itch.io to leave a comment.