I'm working on an isometric (2D)2D game with moderate-scale multiplayer -, approximately 20-30 players connected at once to a persistent server. I've had some difficulty getting a good movement prediction implementation in place.
Right nowPhysics/Movement
The game doesn't have a true physics implementation, clientsbut uses the basic principles to implement movement. Rather than continually polling input, state changes (ie/ mouse down/up/move events) are authoritative for their own positionused to change the state of the character entity the player is controlling. The server performs validationplayer's direction (ie/ north-east) is combined with a constant speed and broadturned into a true 3D vector -scale cheat detection the entity's velocity.
In the main game loop, and I fully realize"Update" is called before "Draw". The update logic triggers a "physics update task" that tracks all entities with a non-zero velocity uses very basic integration to change the system will never be fully robust against cheatingentities position. HoweverFor example: entity.Position += entity.Velocity.Scale(ElapsedTime.Seconds) (where "Seconds" is a floating point value, but the performance and implementation tradeoffssame approach would work well for me right nowmillisecond integer values).
GivenThe key point is that I'm dealing with sprite graphics,no interpolation is used for movement - the gamerudimentary physics engine has 8 defined directions rather than free movementno concept of a "previous state" or "current state", only a position and velocity. Whenever
State Change and Update Packets
When the velocity of the character entity the player is controlling changes their direction or speed, a "move avatar" packet is sent to the server containing the entity's action type (walkstand, walk, run), stopdirection (north-east), and current position. This is different from how 3D first person games work. In a "true" 3D game the velocity is set on(direction) can change frame to frame as the entity andplayer moves around. Sending every state change would effectively transmit a packet it sentper frame, which would be too expensive. Instead, 3D games seem to the serverignore state changes and send "state update" packets on a fixed interval - say, every 80-150ms.
Since speed and direction updates occur much less frequently in my game, I can get away with the new movementsending every state change. In additionAlthough all of the physics simulations occur at the same speed and are deterministic, latency is still an issue. For that reason, I send out routine position update packets (similar to a 3D game) but much less frequently - right now every 250ms additional packets are transmitted, but I suspect with good prediction I can easily boost it towards 500ms. The biggest problem is that I've now deviated from the player's current position for statenorm - all other documentation, guides, and samples online send routine updates onand interpolate between the server as well as for clienttwo states. It seems incompatible with my architecture, and I need to come up with a better movement prediction algorithm that is closer to a (very basic) "networked physics" architecture.
After theThe server validatesthen receives the packet, it gets automatically distributed to all of and determines the other "nearby" players. Client-side, all entities with non-zero velocity speed from it's movement type based on a script (ie/ moving entitiesIs the player able to run? Get the player's running speed) are tracked and updated by. Once it has the speed, it combines it with the direction to get a rudimentary "physics" systemvector - basically nothing more than changing the position byentity's velocity. Some cheat detection and basic validation occurs, and the entity on the server side is updated with the current velocity according, direction, and position. Basic throttling is also performed to prevent players from flooding the elapsed time slice (40ms or so)server with movement requests.
What I'm struggling with is howAfter updating its own entity, the server broadcasts an "avatar position update" packet to implement clean movement predictionall other players within range. I haveThe position update packet is used to update the nagging suspicion that I've made a design mistake somewhere. I've been overclient side physics simulations (world state) of the Unreal, Half-life,remote clients and all other movementperform prediction/lag and lag compensation articles I could find, but they all seam geared toward shooters: "Don't send each control change.
Prediction and Lag Compensation
As mentioned above, send updates every 120msclients are authoritative for their own position. Except in cases of cheating or anomalies, the client's avatar will never be repositioned by the server. No extrapolation ("move now and correct later") is authoritative, client predicts, etc"required for the client's avatar - what the player sees is correct. UnfortunatelyHowever, that stylesome sort of design won't work wellextrapolation or interpolation is required for me all remote entities that are moving. Some sort of prediction and/or lag- there's no 3D environment so each individual state changecompensation is importantclearly required within the client's local simulation / physics engine.
Problems
I've been struggling with various algorithms, and have a number of questions and problems:
Most of the samplesShould I saw tightly couple movement prediction right intobe extrapolating, interpolating, or both? My "gut feeling" is that I should be using pure extrapolation based on velocity. State change is received by the entities themselvesclient, client computes a "predicted" velocity that compensates for lag, and the regular physics system does the rest. For exampleHowever, storingit feels at odds to all other sample code and articles - they all seem to store a number of states and perform interpolation without a physics engine.
When a packet arrives, I've tried interpolating the previous state alongpacket's position with the current statepacket's velocity over a fixed time period (say, 200ms). I'd likeI then take the difference between the interpolated position and the current "error" position to avoidcompute a new vector and place that on the entity instead of the velocity that was sent. However, the assumption is that another packet will arrive in that time interval, and keep entities with their "current state" onlyit's incredibly difficult to "guess" when the next packet will arrive - especially since they don't all arrive on fixed intervals (ie/ state changes as well). Is there a better way to handle thisthe concept fundamentally flawed, or is it correct but needs some fixes / adjustments?
What should happenhappens when thea remote player stops? I can't interpolatecan immediately stop the entity, but it will be positioned in the "wrong" spot until it moves again. If I estimate a vector or try to interpolate, I have an issue because I don't store the correctprevious state - the physics engine has no way to say "you need to stop after you reach position X". It simply understands a velocity, since they might neednothing more complex. I'm reluctant to walk backwardsadd the "packet movement state" information to the entities or another strange direction if their position is too far aheadphysics engine, since it violates basic design principles and bleeds network code across the rest of the game engine.
What should happen when entities collide? If the current player collides with something, the answer is simpleThere are three scenarios - just stop the controlling player from moving. But what happens ifcollides locally, two entities take up the same spacecollide on the server? What if the local prediction causes during a position update, or a remote entity update collides on the local client. In all cases I'm uncertain how to collide withhandle the player or another entitycollision - do I stop them as well? If the prediction hadaside from cheating, both states are "correct" but at different time periods. In the misfortune of sticking them in frontcase of a remote entity it doesn't make sense to draw it walking through a wall that, so I perform collision detection on the player has gone aroundlocal client and cause it to "stop". Based on point #2 above, I might compute a "corrected vector" that continually tries to move the predictionentity "through the wall" which will never be able to compensate and oncesucceed - the remote avatar is stuck there until the error gets totoo high the entity will snap to the newand it "snaps" into position. How do games work around this?