Design Concepts
What these are
These subheadings are....
concepts of things we want
background info on how they usually work
pros and cons of using them
how we implement them
Determinism
Background: Basically, design a simulation where if you feed it the same inputs at the same time in the same order then it would produce the exact same output with zero deviation at all.
Since the simulation has to be perfect, we can't let just anything affect it. If a physics based tire(not simulated) falls off a car and hits a player(simulated), the player isn't going to respond because we can't guarantee that the physics object behavior will be flawlessly reproducible. Think of it like that. If you wanted that to be simulated, you would have to provide enough data to all clients for them to simulate the tire in the exact same way perfectly. This can easily get out of hand.
Pros: It offers some really useful guarantees about the game state that are quite useful in many ways. Inputs can typically be small, as you only need to pass minimal information for the client to calculate the same state.
Cons: Very difficult to design with. Imposes a lot of functional restrictions and demands more of even basic systems so that they can be replayed accurately and not deviate the playback. Can only execute simulation affecting input on the fixed tick rate timing, so fast things could seem slightly unresponsive if the simulation runs slow.
How: In layman terms it means we have to throw away some stuff. Physics and Floating point math are the biggest losers in this situation. You can still use them, you just can't let them affect your simulation calculations in any way so it can remain pure. We also have to force all clients to execute all inputs in the same order that the server does or else they'll deviate. That means packet loss is a bigger issue, and buffers/histories are required.
Lockstep
Traditional Approach
Server waits for input from all players. No one steps forward in simulation. After server collects all inputs, it bounces inputs to clients and Steps. All clients get latest data and Step.
No one can Step until the client with the worst latency reports his input.
Cons: Generally Too slow for fast paced games. We can't slow the entire game down just because one client is lagging. We want the client to have a great experience as that is the whole point of creating a game - and assuming we're making a fast paced game, we clearly must to do something less traditional if we want the benefits of determinism.
Pros: Everybody sees exactly the same thing.
Alternative A
Server and all Clients try to run a simulation at
TickRate
per second. Lets say 60/s. Server will process all inputs received at the time they are received.Inputs are processed and States are sent to the Clients.
Clients apply State data, interpolate to new goals and try to predict the next State while waiting for new data.
Cons: Loose simulation. Since players will be simulating at varying rates and all be unable to properly reach the perfect rate then we're presented with some clients constantly ahead of or behind everyone else due to hardware. If we can guarantee 60/tick rate, use vsync, and guarantee 60 fps, then that would be great, we'd have 100% accuracy. That's not going to happen, though.
Pros: Fast and responsive for the client.
Alternative B
Server runs at
TickRate
and sends a command to clients to do the next Step when it's ready, along with any data for that step. All players are behind in the simulation by their latency RTT / 2.
Cons: Everyone waits for the server to allow them to step forward, so the simulation step consistency is very dependent on the consistency of the latency time. Could easily lead to staggering gameplay. Server in Host scenarios have an objective gameplay advantage.
Pros: Everyone is synced all the time. You're always slightly behind (as with all scenarios) but it's guaranteed to be the correct data.
In the end
The two important takeaways here are:
We need to be disregarding hard lockstep rules in order to give the player a better experience in a fast paced setting that demands responsiveness.
Everyone must calculate their own simulation, but get authoritative corrections from the Server - where the actual game state is historized.
Clients need to be able to reconcile their game state smoothly, and predict the future state as closely as possible.
Simulation
General
Without a real time OS we cannot run the simulation at a fixed hertz tick rate. You might say "Just run it on it's own thread and sleep it to get super accurate timing, dummy." To which I would reply, "No dummy, then literally everything has to be thread-safe, and that would ruin everyone's day.". So yeah, we choose to work around Unity's Update() method for timing so that this doesn't become spaghetti science.
You might ask "What about when the fps gets too low and the Simulation can't update fast enough?"..... Well, then you need to design your game better. The simulation will get corrective attempts from the server, but this is a game design issue, not a problem with the simulation.
On average, we'll get pretty close to the desired fixed rate on the simulation tick rate because we examine historically if we're overshooting the target time and make adjustments, as well as tracking the missed time and using it for the next timing goal. Without this system, we run into a situation where applications running at high framerates will Tick more accurately in time, while slower systems will miss by a lot and tick slower.
Server Simulation
The server receives input from clients, calculates result states, and returns them to the player.
Client Simulation
The client sends inputs to the server. Due to network latency we can make the safe assumption that clients will run their simulation in the future by some amount of time. The server receives client input after RTT / 2
and calculates state results which are sent back to the client for validation of the current state.
Prediction
<WIP>
Interpolation
This is pretty straightforward. During the update loop everything basically blends between the previous data and the latest data. Game.TweenTime
offers a normalized value for progress between tick frames and Game.SimDeltaTime
offers the 'fixed delta time' of the Simulation.
<WIP>
Conclusions
Determinism: Perfectly reproducible simulation. Lockstep: All clients state-synced. Prediction: Clients estimate what happens next. Interpolation: Clients blend between states smoothly.
We want all of these things, but we'll have to only take parts from them in order to actually get feasible scope.
Last updated
Was this helpful?