Download

running physics in a separate thread: is this a viable approach?

I’m working on a game that has moderately complex custom physics code that executes per actor. Currently it’s hung off a custom timer that I set up like so and run 30 times per second:


   tm.SetTimer(PhysTimer, this, &UPhysMovementComponent::CalcPhysics, PhysicsRate, true);

This is okay. However, it won’t scale well to a very large number of objects, so I want to punt this off to a separate thread, and have the actor Tick() function do only the very simple “tail end” of the physics such as vel=vel+accel type stuff.

I found this tutorial Rama made, which I guess will be helpful when I get to writing the code. There’s one thing I’m unclear on though. I don’t need to create or destroy objects in my physics thread, but I DO need to modify some instance data, which that page suggests is a bad idea.

My plan is to set up a physics thread that iterates through the global actor list, running physics on each in turn. It would use some kind of lock (FCriticalSection? FScopeLock? what’s the right thing?) to avoid collisions between itself and the game thread. Something like this in pseudocode:



  Physics thread(s):
     For each actor:
        Grab a lock for this actor
        Run the heavy duty physics
        Release the lock

  Game thread actor Tick() fn:
     Grab a lock
     Run the light duty physics & update actor positions
     Release the lock


Is this a viable way to go? And what flavor of UE4 lock do I want to be using? What issues are there with traversing the set of actors in a separate thread like that, where the main thread can delete them, even if this physics thread never will?

Thanks for any insights!

I’d be interested in this too so if anybody knows do chip in. I currently run my physics every frame but it’s going to hit me hard when there’s a few hundred objects in the level. The problem is that my physics relies on things like line traces and whatever else, so don’t know if it’s entirely possible to make it ‘thread-safe’.

TheJamsh, do you know about the async line trace functions? I experimented with them and posted about that here. I think a more complex scene would see a bigger percentage win, but it was still a benefit for me even with a very simple scene. Basically you get a handle back that has an internal ping-pong between alternate frames, so you have to deal with one frame of latency. You kick off the query on frame N, and query the handle for completion on N+1. In exchange for that, it kicks the work off to some other thread. I don’t fully understand what other thread that is, but presumably it’s not the one you’re calling the async function from.

At the very least, it seems like that implies that if you can tolerate the result latency, you can get the actual line tracing work off onto some other thread. You might be able to combine that with doing whatever other physics you need to do on your own thread, to get almost everything out of the main game thread except consuming the result.

Then again, I might not have any clue what I’m talking about :p. I’m still very much in exploration and learning mode.

I’m using the async stuff in what I’ve built so far. I should probably do some more investigation to better understand where the work goes. I haven’t had much time to investigate the threading architecture yet.

Just wanted to share my 2 cents on this :slight_smile:

In the past i worked a lot with PhysX SDK.
If i remember correctly they using what they call double buffered data.

So for custom physics in UE4 u could do a bit the same and be able to do with very few locks.

The main idea is that u store all variables used by the physics calculation in a structure.
Create one or more worker threads for running the physics. (TaskDispatcher with TaskQueue)
At the start of the frame, start simulating the physics by locking the TaskQueue which will cause the simulation threads to be paused
Look trough all actors (no lock needed if in GameInstance::Tick()?) and create a new task for each actor containing a copy of the physics data.
This allow using the physics data on the actor without locking while the physics are simulating.
Unlock the TaskQueue to let the simulation threads continue and process the physics tasks.
At the end of the frame wait for the physics tasks to complete and copy the data back to the actors.

Its also possible not to fetch the simulation data at the end of the frame if u want to allow the physics simulation to take 2-3 frames for example.
What i usally did with physx was calling the FetchResults at the begin of the frame (can return completed or in progress) and start simulation if fetch return completed.

This way the only lock u have is the task queue lock.
In PhysX it still work different as u have read and write locks. In the PhysX docs there is somewhere explained how the double buffering works exactly.

Ofcourse the worker threads will lock the queue for each task, but in theory u could make those lockless and have a simulation state stored somewhere, including a lock.
As the queue will not change during the simulation start/end, so u could make an indexed list instead of queue and use an atomic counter within the worker threads to get a thread safe index on the list for processing a task.
This should be bit more performant as a locked queue. There are also some samples to create lockless queue’s but never put much time looking into those.

I have no clue how to create threads or locks in UE, but if u interested i can post a code sample of a multi threaded task dispatcher i used in a MMO server i created while ago.
The code is fully C++11 and contains the task dispatcher, task class with function delegate, delayed task dispatcher (trigger task at certain point in time)

I think I read somewhere that it can break the sync between Unreal collision and PhysX Collision , so your object could be someplace else for the physX world than in the Unreal engine world