Networked Physics with PhysX

Rewind & replay would become very expensive very quickly when you try to use it with a large number of objects :smiley:

I find myself then confused as to how other games & engines do it, with the exception of Source Engine which has deterministic physics.

Rocket League uses UE3 and the Bullet Physics Engine, though it’s relatively small scale in terms of its physics simulation.
Astroneer is UE4 based and has loads of multiplayer physics.
Crackdown 3 uses UE4 and has a massive amount of multiplayer physics. I understand they are using some cloud based magic for some of the physics, but not all of it. Have we got any speculation on how they are keeping physics states in sync between clients?

Short answer is that they don’t, but it’s good enough for us not to notice most of the time. You only ever replay physics for the local object that the client controls. Other objects just receive transform and velocity updates, and the objects are smoothed between those updates. You can use Velocity and remote client input to do a bit of extrapolation which helps seal the deal as well.

In the case of Crackdown, they probably wrote their own very simple Physics solver based on a syncronised seed, but I don’t know.

You could add it to any physics object but it would get very expensive very quickly in terms of CPU time and bandwidth. Even with only your main vehicle using rewind/replay it takes a lot of your bandwidth but constant stream of updates is important for it work properly.

Btw I finished my client side prediction component and it is working better than I expected, only nightmare left is collision with dynamic objects :rolleyes:

But what about other objects that the client interacts with. Lets say a player pushes on a barrel, in a default implementation the barrel (a simulated object that’s receiving old location updates from the server) would jitter against the player. You wouldn’t be able to do simple velocity/location extrapolation either should there be a wall or other object in front of the barrel that would collide with it and prevent it from moving, right?

1 Like

That’s correct, which is why for the most part collision between two dynamic objects over the network is an unsolvable problem. Even Ubisoft haven’t cracked it yet, there’s still a lot of research to do:

http://www.gdcvault.com/play/1024597/Replicating-Chaos-Vehicle-Replication-in

Elhoussine linked me to this on Twitter. They take some interesting approaches. They use P2P, but funnily enough it looks like S2C works better for this.

1 Like

BlueMan: Thanks, I think I just have to patiently tweak values until it looks good. But before that I’ll do some research on how to minimize the error between the simulations to not rely on smoothing as much as I do at the moment.
How big are the errors you have to smooth out? I’m interested in how far you tweaked the actual system before you started smoothing out the remaining differences.

That gave me some ideas how to handle dynamic collisions… :rolleyes:

That vehicle you see in the video is around 7 meters in length because I messed some things on import and went with it. In this case max smoothing kicks in when the error is around 1 to 1.5 meters but with normal sized vehicles it would be around 0.5 meters. Without the smoothing you can see a small amount of snapping when vehicle changes direction very fast, for example collisions, rolls, jumps…

Be interesting to see how you handle it for sure, what you have right now would fullfill my needs though :stuck_out_tongue:

I wish I had more time to spend on this :frowning:

@blue man
Hey so in your client prediction videos what do the different colored meshes represent? Thanks

Hey, green - position from the server, red - old position from the client, blue - current predicted position

1 Like

So if blue is the current predicted position, what does the actual vehicle represent? Its ahead of the predicted position?

The actual vehicle is a result of smoothing. It seems like it is ahead but that is because those debug things are not updated every tick.

Are you using the same model for smoothing as the exponential smoothing in CharacterMovementComponent? That’s what I’m trying to use but it still reacts to the occasional update mismatch jitter (even with very slow interp time) and I don’t know if its the smoothing or something else I’m experiencing. Also thanks for replying. Your work looks great so far.

If MaxSmoothNetUpdateDist is set too low, then if you get a big correction you won’t get smoothing, it’ll snap.

The defaults for Character movement are fine because human pawns move slowly. You have to adjust the smoothing tolerance values to compensate for the speed at which your object moves. Smoothing is supposed to take place over short distances to eliminate small amounts of jitter.

1 Like

I’m not actually using a max dist. Experiencing this jitter with a slower interpretation in low ping. But it’s not like bad jitter. It’s like a hiccup every second or so, and it happens when the server update and the client update mismatch a frame (no server update, server update, no update, update, no update, update, no update, no update, update - two frames in a row where we didn’t get an update from the server). Also I should note in using fix time stamp if you didn’t see my earlier posts. And I’m not doing rewind replay because I’m not doing any client prediction yet. Trying to figure out why it doesn’t look smooth in a no lag, no prediction scenario.

I’ve submit a pull request for activate simulation fixed delta and enhanced determinism directly in the project settings:

I’m working on rewind / replay algorithm, but I’ve a problem on simulation.

I’ve created a new World (as we know) that initialize automatically the PhysX scene which I’ll use for rewind / replay process.

After moving the PxActors from the main scene to the new scene, is executed this code that should execute the simulation 10 times:



	for (int32 a = 0; a < 10; ++a) {
		RRWorld->SetupPhysicsTickFunctions(1.f/60);
		RRWorld->GetPhysicsScene()->StartFrame();
		RRWorld->GetPhysicsScene()->WaitPhysScenes();
		RRWorld->GetPhysicsScene()->EndFrame(nullptr);
	}


The problem is on that line RRWorld->GetPhysicsScene()->WaitPhysScenes(); for some reason the execution stop forever. There’s no crash the executions is blocked.

Blu man, how do you execute the simulation?
Do you talked about calling the function PXScene::simulate, So you skip the FPhysScene simulation?

There is something that I’m missing?

I’m calling simulate function on PxScene and right after that I call fetch function. Also I’m not creating a new scene with UWorld but you need to have a separate UWorld if you want to trace in your scene. A new PxScene also gets created when you initialize FPhysScene and you can set in your new UWorld to use your scene.

I don’t know why but I’m getting this error:


Exception thrown at 0x00007FFFE85C72E7 (PhysX3PROFILE_x64.dll) in UE4Editor.exe: 0xC0000005: Access violation reading location 0x0000000000000000.

At this line: PScene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC, DynamicActors.GetData(), DynamicActorsNum);

Here I’m taking only the Dynamic actors for a test.
Did you do in this way?



	PxScene* PScene = GetWorld()->GetPhysicsScene()->GetPhysXScene(PST_Sync);

	const PxU32 DynamicActorsNum = PScene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC);
	TArray<PxActor*> DynamicActors;
	DynamicActors.AddUninitialized(DynamicActorsNum);
	PScene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC, DynamicActors.GetData(), DynamicActorsNum);
	
        FPhysScene* PS = new FPhysScene();
	PxScene* RRPScene = PS->GetPhysXScene(PST_Sync);

	PScene->removeActors(DynamicActors.GetData(), DynamicActorsNum);
	RRPScene->addActors(DynamicActors.GetData(), DynamicActorsNum);

	for (int32 a = 0; a < 2; ++a) {
		RRPScene->simulate(1.f / 60.f);
		RRPScene->fetchResults(true);
	}
	RRPScene->removeActors(DynamicActors.GetData(), DynamicActorsNum);
	PScene->addActors(DynamicActors.GetData(), DynamicActorsNum);

	delete PS;
	PS = nullptr;