Networked Physics with PhysX

@OmaManfred
I am aslo working on client side prediction for my project. It is almost woking (almost is the key word here :rolleyes: ) but I am stuck at actually replaying the physics. I went through your explanation about 10 times and I don’t understand how to replay the physics with physx.

FWIW I’ve written this kind of system into UE4 using PhysX and it works really well. However, it wasn’t exactly straightforward, you have to revisit a fair amount of assumptions that UE4 builds on top of and i’m sure this is where you were running into trouble.

Btw UE4 already syncs server time for you in the GameState, so you can just use that as a starting point, no need to re-invent the wheel.

And for the record, “Ping” is round trip time not one-way time.

I got it mostly working, I already got the roundtrip time and history buffer working but I was stuck at fast forwarding the physics and I found the way to do it. Basically I am calling PxScene::simulate() to fast forward. The problem here is that It also fast forwards other physics objects in the scene so right now I am trying to create a new Physics Scene and move my vehicle to that scene so it doesn’t mess up other objects.
I am creating the scene like this FPhysScene* NewScene = new FPhysScene(); and that part is working, I think but when I try to add a new PxActor to the scene the editor crashes without an error message.
When I debug it through Visual Studio I get this error “access violation writing location”.

How is the Bullet integration looking? I was thinking of doing a Bullet-based car game…

If you isolate your vehicle to its own scene, then it won’t be able to interact with anything else. Probably not what you want.

Why not just save a snapshot history for all dynamic objects in the scene? Then you’re rewinding & replaying everything together and won’t have any fast forward issues.

If you want your predictions to be accurate, it’s better to think about saving snapshots of the entire world state rather than just one or two actors.

My plan was to also move the other actor that are near the vehicle. It seems like ue4 doesn’t really like when you move actors between physics scenes so I think I am going to do everything in the main scene and before the fast forward happens it will collect the rotation, location… of every dynamic object and after the fast forward it will set everything in its original state.
So everything that happens normally will happen when I fast forward the physics, things like substepping…?

Are you using a fixed physics timestep? If not, that’s the first thing you need to do. The engine doesn’t support this, you have to add it. Semi-fixed and variable timesteps won’t give you accurate predictions (on any physics engine).

Your approach won’t work well because you’re mixing objects in different time streams. The vehicle is in the past, but everything else is at current time.

Better way to think about it is rewinding time and catching up (predicting) to the current time, rather than fast-forwarding. In order to accurately do that, you need to know the entire state of the world at that time in the past.

Fixed timestep requires engine source modification?
I know I should probably rewind the whole scene or maybe just rewind the actors that originally collided with the vehicle as someone suggested earlier in this thread. For now I just want to get it somewhat working.

For physics engine, yes. Unreal doesn’t support fixed timesteps by design (it’s intentionally done this way). You can force the rendering to tick at somewhat fixed timesteps and then do physics without substepping (that way physics would always tick only on rendered frames) but you wouldn’t be fully in control then either.

edit-> fixed framerate also only works if your target hw can render the game that fast, if it doesn’t it would change physics ticking rate too in that scenario.

Thank you for the explanation.

After 3 weeks of trying I finally got it working and I can see the problem now.

Blue man, what did you end up doing? I’ve been trying to figure out how to rewind, or save/clone a physx scene, or create a new scene that only contains actors, forces, and constraints in a certain area.

I was going to try to set only the server to fixed timestep, and have the clients maintain an old scene. When a client receives position updates with a timestamp attached to it, it takes the old scene and simulates forward until it hits the sent informations timestamp, then updates the positions of the objects in the old scene, and then simulates forward again. But I’ll admit this is far outside my area of experience, so I don’t know if that’d work.

@scamp - Is there a possibility that you can shed more light on what changes you’ve made to get this working reliably, particularly if you’ve made any engine changes and how you’re doing your replay?

I have a template Networked PhysX project that’s getting close to achieving this using a hybrid of what Character Movement Component does, and using PhysX. There are still a few roadblocks in my way. In the end I want to have this project on GitHub so that everybody can benefit from it.

Sorry for the late response, I decided to do everything in the main physics scene because ue4 is not very happy when you move physics bodies between scenes. To replay the physics you have to get the physics scene form the world ( GetWorld() ) and then convert it into PxScene* and when you do that you can call simulate(Time) function on PxScene*. Before you call it you also need to set all the input and call your physics function (your function where you calculate physics). If someone knows how to properly create a new physics scene please let me know, it would be better to do this stuff in a separate scene I think.

It replicates perfectly when the vehicle is driving but when it is in the air it goes out of sync, still need to find way to solve that.

How are you rewinding the scene to the previous state? Do you save a buffer of the entire physics scene or just one object? Although @scamp 's idea is to store a buffer for the whole scene, that probably isn’t going to scale very well when you have a lot of objects or a huge world.

I’m still trying to do this by just applying the rewind and replay to one object only (the players’ pawn). The ideal approach IMO would be to duplicate the PxScene with all static geometry (and ensure it updates if you create/remove geo at runtime), and then be able to add and remove a single dynamic object at will, which is the players’ pawn. You could then just resimulate the PxScene with the deltatime that you saved with each frame.

There’s still the issue of resolving dynamic collision then… but i’m willing to tolerate that rather than try to duplicate the entire scene and store 96+ duplicates of it.

Right now I am just setting the vehicle to the corrected location/rotation sent from the server which is in the past and then it goes into a loop and fast forwards the scene. I also think it my get quite heavy on the performance if I store a buffer for the whole scene. I might just store a buffer for the objects that are close to the vehicle.

But if you’re fast forwarding the scene, doesn’t that mean that other objects also do the same thing?

Yes, I plan to solve that by just storing the position/rotation for just that one moment before the fast forward happens and when the fast forward is complete it will go through all dynamic objects and set the location from the history. It is still not the best solution but it is better than making a buffer for all objects every tick.

Out of interest, does anybody actually know how to duplicate or create a new physX scene in Unreal yet and insert an actor into it? Going to try and create an empty PhysX scene for now and resimulate just one object.

EDIT: Currently having a look at how PHAT creates physX scenes on the fly.

I tried to directly insert an actor directly into PxScene and the editor crashed, I also tried to insert it through FPhysScene and I got LNK error.

I’m just trying this for now. Most annoyingly, it seems like I can’t get the relevant headers for PhysX unless I compile the engine from source. Binary build fails because it cna’t find Px.h. Soo irritating.



	// Now Simulate the PhysX Scene
	FPhysScene* Scene = GetWorld()->GetPhysicsScene();
	if (Scene)
	{
		PxScene* WorldPxScene = Scene->GetPhysXScene(PST_Sync);

		// Scratch Buffers
		UPhysicsSettings* Settings = UPhysicsSettings::Get();
		ASSERTV(Settings != nullptr, TEXT("Invalid Physics Settings"));

		int32 SceneScratchBufferSize = Settings->SimulateScratchMemorySize;
		if (SceneScratchBufferSize > 0)
		{
			// Temporary Scratch Buffer
			uint8* Buffer = (uint8*)FMemory::Malloc(SceneScratchBufferSize, 16);

			WorldPxScene->simulate(InMove->MoveDeltaTime, nullptr, Buffer, SceneScratchBufferSize, true);
			WorldPxScene->fetchResults(true);

			// Free the Scratch Buffer
			FMemory::Free(Buffer);
		}
	}


really don’t want to switch to a non-launcher build for this…