Multiple physics worlds for parallel prediction jobs?

For my project I need to predict trajectories for dynamic bodies. I have code to create physics worlds from entity queries and running the prediction entirely on worker threads is possible with a small modification to the physics package.

The final piece of the puzzle is to create a parallel job. As I know my worlds will rarely change I want to reuse them. The problem is how to get one of these worlds to a thread for performing the actual work.

Currently I create maxWorkerThreads + 1 worlds and schedule a IJobFor with same nr array length parameter (alternatively I could use NativeThreadIndex). I can not pass a NativeList to my job as Native structures can not be nested. I created my own List which is a NativeList but without the safety features. This allows me to pass the PhysicsWorlds in to the job and the job runs fine, however when I enable memory leak detection I get errors as it thinks I’m leaking local variables which are instead stored in a List of the type mentioned above.

I am really at a loss here, I can hardcode a maximum number of physicsworlds with fields for each individually, but this is far from ideal, any way I can store a dynamic number of physicsworlds without tripping up any of the safety systems, or associate them with IComponentData somehow? I do not care if I lose the safetey systems for these worlds if it helps :slight_smile:

Worlds are closely tied to ECS. Does each of your prediction runs really require separation? Cannot you just have one predictive world and step it using your inputs from multiple projectiles? Or would this cause odd interactions you don’t want?

It’s not about separation, I have multiple dynamic bodies per world set up not to interact with eachother through their filters, it’s about running a parallel job

I want to do a lot of prediction, ideally at full precision (timestep)

This is what I do. You can predict everything you should separate out our graphics etc.

    void Start()
    {
        locECSWorld = new World("lockStepWorld", WorldFlags.Simulation);
        var systems = DefaultWorldInitialization.GetAllSystems(WorldSystemFilterFlags.Default);

        DefaultWorldInitialization.AddSystemsToRootLevelSystemGroups(locECSWorld, systems);

        FixedStepSimulationSystemGroup fixGroup = locECSWorld.GetExistingSystem<FixedStepSimulationSystemGroup>();
        fixGroup.FixedRateManager = new FixedRateUtils.FixedRateSimpleManager(MyFixedTimeStep);
}

    private void updateOnce(inputData myInputData)
    {
     //do input stuff here
     locECSWorld.Update();
     }

Just copy ECS data when you need to make a new world.

This is way too slow, it can only predict a single frame without going back to the main thread and incurs prohibitive overhead for scheduling. I’m looking to predict tens of single bodies tens to hundreds of frames which is feasible given the approach outlined above, all I need is a way to get multiple worlds to a parallel job

Did you take a look at https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/UnityPhysicsSamples/Assets/Demos/6.%20Use%20Cases/ImmediateMode? I know there is only one extra world in there, but it’s simulated through a job and shows what you should do for lightweight prediction.

thats the pool one right? Yeah that’s where I started, I found that I had to modify the physics package to predict beyond one frame without going back to the main thread

I am currently predicting 29 independent spheres 180 frames in 2 and a bit ms on a single thread, which is already pretty good imo

If I store the worlds in fields on the system the memory leak detection does not get triggered and I can trigger a parallel job, I am seeing longer wall times though and an order of magnitude more total resources consumed, not sure what is causing this…

The ImmediateMode demo is not good for heavy prediction of everything but is fine for single player prediction of weapons trajectories I guess. Stepping a world from update and adding whatever systems and entities you want will just gives you total control.

If you try doing complex stuff using the ImmediateMode demo as an example the complexity will just explode. I actually think the use cases for StepImmediate are extremely limited and you sound like you are beyond the limit.

Yeah StepImmediate is designed for lightweight simulations, nothing too heavy. But we did have asks for such stepping mechanism, for isolated small worlds, that’s why we did it. It definitely improved performance a lot in this use case of pool prediction.

Hi @Bas-Smit , I don’t think you can have native collections in native collections inside a Job. For further info about that and any potential workarounds, I’d suggest posting a thread on DOTS subforum.
It sounds like you’re quite familiar with physics-related stuff, like StepImmediate, so I thought it’d be useful to suggest contacting DOTS people, who should know all the details and might be able to suggest something.

1 Like

memory leak detection does not support nesting unfortunately, tertle suggested using proxys which is a viable approach but a bit too heavy handed for my purposes

I ended up using a List with the safety features removed to allow for nesting, while storing each world in a field to satisfy the memory leak detection…

If I ever figure out why the parallel job does not provide any gains I’ll post the results here, I am pretty impressed by the results so far

@Bas-Smit This may be overly simple for your use case, but if you or anyone else like me is in a situation where you wanted the additive scene equivalent of Unity’s default Physics system, I did this on start in a MonoBehaviour:

physicsSceneWorld = DefaultWorldInitialization.Initialize($"{gameObject.scene.handle}"); ;

1 Like