How can UE4 be converted to fixed frame step (aka deterministic) physics?

I’ve been having trouble wrapping my head around it, but I think I’m close to the solution.

SubstepSimulationStart() in PhysSubstepTasks.cpp seems to be where the solution lies. The engine seems to call this function once for each substep until we reach the last one. The problem is, no matter what combination of max substep time or max number of substeps used, that final substep will almost never have a consistent DeltaTime. No matter how accurate we get, that will introduce a desync, which is unacceptable for my use case.

I think I need to modify this chunk of code to use an accumulator, but I’m probably just too tired to figure it out right now.


	++CurrentSubStep;	

	bool bLastSubstep = CurrentSubStep >= NumSubsteps;

	if (!bLastSubstep)
	{

		Alpha += StepScale;
		TotalSubTime += SubTime;
	}

	float DeltaTime = bLastSubstep ? (DeltaSeconds - TotalSubTime) : SubTime;
	float Interpolation = bLastSubstep ? 1.f : Alpha;

#if WITH_VEHICLE
	if (VehicleManager)
	{
		VehicleManager->Update(DeltaTime);
	}
#endif

	SubstepInterpolation(Interpolation, DeltaTime);

I actually had the first response in that thread, but thanks anyway. :slight_smile:

“If you want to go with Free the physics route you should take a look at PhysSubstepTasks.cpp where you can change the way we compute the number of sub-steps and delta time.”

I’m trying to figure out exactly what that change is.

As a followup, the farthest I got with this problem before realizing that I didn’t need to solve it for my specific purposes is to add a static accumulator to the FPhysSubstepTask class. The problem to solve, then, is to create some means of initializing that value to zero before each match. It’s less than ideal for this engine.

It’s worth noting that fixed-frames isn’t necessarily deterministic, and nVidia PhysX is far from Deterministic at all.

Even if you fixed and synced frames between server and client, and sent the same input data - the results would slowly drift over time.

Sounds like no matter what, if you want to use input and rollback-based netcode, you’ll at the very least have to roll your own physics (or use one that is designed to be deterministic).

I am looking at 4.11.2, here is some code in PhysSubstepTasks.cpp:

Why does UE4 not set SubTime to a constant, so we can get a fixed delta time for physical calculation?

two more questions : is substepping working on mobile now? What is the usage of “substepping async”? I am not sure the role ‘async’ physical is playing in UE4.

You dont want a fixed timestep for physics substepping. The system is perfect as is. It basically calculates how bigger the delta seconds between each frame is, then runs an X number of substeps accordingly. If that wasn’t the case you would see projectiles going through walls for example much more times. Every actor has a tick group (look into that) and on the project settigns you can change the amount of substeps (look into that too).

From my understanding, the code shows SubTime depends on the Frame Delta time. I agree it is good for local calculation, but I hope to decouple physic from framerate as much as possible, So I can let client predict the physical reaction for a short time, using physx or my own implemention with existing UE4 physical calculation facility.

By the way, I haven’t find the async substepping code yet, does that ‘async’ means it calculate physical in separate thread decoupled from game frame rate condition? If so, how can tell UE4 use async substepping physical for an actor?

vgambit, have you suceed to rewind the physical calculation? What is you solution? I thought, If we get fixed substepping, it is possible to predict physical result for a short time like 500ms, and server fix the drifting at a fixed rate, making network physic possible.

I read another post, which said use physic on server only and then replicate, have you tried this method?

The physics will still drift over time due to different outcomes in the floating-point operations, fixed timestep still doesn’t mean you’ll get the same results on different machines. You will always have to sync the gamestate now and again.

See here: http://www.nvidia.com/object/physx_tips.html#Network
And here: Floating Point Determinism | Gaffer On Games

If you want a deterministic solution, you’ll have to swap out the physics engine (collisions and all) for something else. By fixing and syncing the timestep accross all players, you should get very close results, but I would still recommend doing sanity checks now and again to make sure everything stays in line.

You should run the physics simulation both Server and Client side, and send small adjustments from the server to keep the client in check. If you only simulate the physics server-side, then your movement will feel unresponsive on the client even with a few milliseconds of ping - and responsiveness of the game will also be tied to your network rate.

1 Like

This makes me wonder - how have you implemented client-side prediction in your multiplayer tank game? Short of having client-authoritative movement physics, I can’t see any other way. And client-side prediction without a fixed timestep seems extremely difficult.

EDIT: To back up TheJamsh, however, from Nvidia docs (Network Physics section):

Not yet, currently it’s all server side and therefore horrendously unresponsive with lag (hence I need to re-write that section). I think the default engine vehicle movement allows for some difference, and just sends a hard rubber-banding update to the client when they go out of sync (which is awful). Mind you, UT3 worked that way…

But yeah, fixing the timestep of the physics simulation is pretty much imperitive so getting this close to working.