To use Simulation.StepImmediate I need to provide a SimulationContext which I can simply create and Reset as needed. To schedule a ICollisionEventsJob I need to provide a Simulation which contains a SimulationContext, but it’s internal and I can not Reset it through the Simulation. I’m assuming I need to set up another world with all the physics systems to receive collision events, or can this be made to work?
You can, but you can’t use ICollisionEventsJob, you need to do a foreach through the events in the context - foreach (CollisionEvent collisionEvent in simulationContext.CollisionEvents). That’s what ICollisionEventsJob does anyway, so just wrap it in an IJob.
Cool, now all I need is a public version of ScheduleReset
You can use public void Reset(SimulationStepInput stepInput)
and generally should do it before each StepImmediate (to support changing number of bodies between steps).
Yeah but that needs to run on the main thread, Im referring to the comment in Simulation.cs, line 90. Im already spending .3 ms on some very simple prediction
@petarmHavok resetting is safe as long as the amount of bodies dont change right? I could just make ScheduleReset public?
internal JobHandle ScheduleReset(SimulationStepInput, JobHandle, bool)
Edit: well it runs but at 1.2 ms it is about 4 times slower
Rather than exposing ScheduleReset, I’d suggest creating a new public method ScheduleResetEventStreams that will schedule event data allocations and won’t touch m_InputVelocities and m_SolverStabilizationMotionData. With that, you can do everything in jobs, but of course need to make sure they depend on each other (reset->step->read event streams) and number of bodies doesn’t change.
We’ll definitely look into improving this, so people can do full reset in jobs. Thanks for the feedback!
Hi @Bas-Smit , I think that you can even support varying number of bodies with ScheduleReset, but only in StepImmediate case. To be safe, you can create a new method (ScheduleReset2) that schedules all native array disposals and allocations (including m_InputVelocities and m_SolverStabilizationMotionData) and returns a combined job handle. Then pass that handle as input dep to the job that will perform StepImmediate.
thanks, because I have very few bodies this is what I am seeing in the profiler once the scheduling is done
I’ll try getting everything to happen in a single job, looks like that could be a lot more efficient?
If I understand correctly all I need to do, provided the number of bodies do not change, is resetting the event streams after stepping. Unfortunately the stream only exposes a job to do so. I also tried just diposing and allocating them again in the job, but I am not allowed to dispose of the streams created outside the job because of conflicting allocators
The key is to create a Reset method that can allocate using Temp allocator. After that you can create a ResetStreams method that Disposes of the streams and allocates new ones, also using Temp. Now stepping 2 bodies 30 frames runs at acceptable speed and can run on a background thread. Thanks @milos85miki
SimulationContext:
public void Reset(SimulationStepInput stepInput, Allocator allocator = Allocator.Persistent)
public void ResetStreams()
{
CollisionEventDataStream = new NativeStream(WorkItemCount[0], Allocator.Temp);
TriggerEventDataStream = new NativeStream(WorkItemCount[0], Allocator.Temp);
}
Job:
public void Execute()
{
var simulationContext = new SimulationContext();
simulationContext.Reset(StepInput, Allocator.Temp);
for (int i = 0; i < Steps; i++)
{
// ...
simulationContext.ResetStreams();
}
}
Shame it takes 6.5 ms on mono though
EDIT: remove Dispose
Just be careful with event streams on Temp allocator, if you wanted to iterate through them on the next frame (not saying you do, just raising awareness), that memory will not be available.
Also, you shouldn’t need to dispose Temp memory, it will be done for you at the end of frame.