August 2021
Posted 3 years ago
Imagine you're shooting a gun in game. The client runs the prediction shoot code, which calls a "ShootEffects" function, which plays the sound and draws the muzzle flash. Then the server runs the actual code which calls 'ShootEffects' too, which is an RPC, so it sends a network message to the client to call the function.

We need the server to call that RPC on all of the clients so they hear the sound and see the effects. But the predicting client is getting that message twice. So they play the sound twice.

The Old Way


So I had a system in place where the predicting client would assume it had already run any RPCs sent during its command. So when it came in it'd ignore it and not run it.

That worked but sometimes the server sent an RPC that it didn't want the client to suppress. Like if you shoot someone, and they die - they only die on the server, and it happens during the command so the predicting client would ignore any RPCs sent.

So I added Prediction.Off(), which would turn suppression off in its scope. Except people obviously were confused by it because they put it everywhere, even in client only code.

The New Way


If we can make things easier and simpler we should. This was turning out to be a big enough confusion that it was worth fixing.

So when the client calls an RPC function client-side now they'll make a note of it. 

When they get an RPC from the server they'll supress it if they already ran it during the prediction.

This is simpler and automatic. It has the advantage too that if the parameters of the call aren't the same then the function is run twice - alerting the developer that their prediction code is wrong.