Skip to main content
added 3852 characters in body
Source Link

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:

  1. 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.

  2. 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?

  3. 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.

  4. 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?

I'm working on an isometric (2D) game with moderate-scale multiplayer - 20-30 players. I've had some difficulty getting a good movement prediction implementation in place.

Right now, clients are authoritative for their own position. The server performs validation and broad-scale cheat detection, and I fully realize that the system will never be fully robust against cheating. However, the performance and implementation tradeoffs work well for me right now.

Given that I'm dealing with sprite graphics, the game has 8 defined directions rather than free movement. Whenever the player changes their direction or speed (walk, run, stop), a "true" 3D velocity is set on the entity and a packet it sent to the server with the new movement state. In addition, every 250ms additional packets are transmitted with the player's current position for state updates on the server as well as for client prediction.

After the server validates the packet, it gets automatically distributed to all of the other "nearby" players. Client-side, all entities with non-zero velocity (ie/ moving entities) are tracked and updated by a rudimentary "physics" system - basically nothing more than changing the position by the velocity according to the elapsed time slice (40ms or so).

What I'm struggling with is how to implement clean movement prediction. I have the nagging suspicion that I've made a design mistake somewhere. I've been over the Unreal, Half-life, and all other movement prediction/lag compensation articles I could find, but they all seam geared toward shooters: "Don't send each control change, send updates every 120ms, server is authoritative, client predicts, etc". Unfortunately, that style of design won't work well for me - there's no 3D environment so each individual state change is important.

  1. Most of the samples I saw tightly couple movement prediction right into the entities themselves. For example, storing the previous state along with the current state. I'd like to avoid that and keep entities with their "current state" only. Is there a better way to handle this?

  2. What should happen when the player stops? I can't interpolate to the correct position, since they might need to walk backwards or another strange direction if their position is too far ahead.

  3. What should happen when entities collide? If the current player collides with something, the answer is simple - just stop the player from moving. But what happens if two entities take up the same space on the server? What if the local prediction causes a remote entity to collide with the player or another entity - do I stop them as well? If the prediction had the misfortune of sticking them in front of a wall that the player has gone around, the prediction will never be able to compensate and once the error gets to high the entity will snap to the new position.

I'm working on an isometric 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.

Physics/Movement

The game doesn't have a true physics implementation, but uses the basic principles to implement movement. Rather than continually polling input, state changes (ie/ mouse down/up/move events) are used to change the state of the character entity the player is controlling. The player's direction (ie/ north-east) is combined with a constant speed and turned into a true 3D vector - the entity's velocity.

In the main game loop, "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 entities position. For example: entity.Position += entity.Velocity.Scale(ElapsedTime.Seconds) (where "Seconds" is a floating point value, but the same approach would work for millisecond integer values).

The key point is that no interpolation is used for movement - the rudimentary physics engine has no concept of a "previous state" or "current state", only a position and velocity.

State Change and Update Packets

When the velocity of the character entity the player is controlling changes, a "move avatar" packet is sent to the server containing the entity's action type (stand, walk, run), direction (north-east), and current position. This is different from how 3D first person games work. In a 3D game the velocity (direction) can change frame to frame as the player moves around. Sending every state change would effectively transmit a packet per frame, which would be too expensive. Instead, 3D games seem to ignore 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 sending every state change. Although 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, but I suspect with good prediction I can easily boost it towards 500ms. The biggest problem is that I've now deviated from the norm - all other documentation, guides, and samples online send routine updates and interpolate between the two 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.

The server then receives the packet and determines the players speed from it's movement type based on a script (Is the player able to run? Get the player's running speed). Once it has the speed, it combines it with the direction to get a vector - the entity's velocity. Some cheat detection and basic validation occurs, and the entity on the server side is updated with the current velocity, direction, and position. Basic throttling is also performed to prevent players from flooding the server with movement requests.

After updating its own entity, the server broadcasts an "avatar position update" packet to all other players within range. The position update packet is used to update the client side physics simulations (world state) of the remote clients and perform prediction and lag compensation.

Prediction and Lag Compensation

As mentioned above, clients 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 required for the client's avatar - what the player sees is correct. However, some sort of extrapolation or interpolation is required for all remote entities that are moving. Some sort of prediction and/or lag-compensation is clearly 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:

  1. Should I be extrapolating, interpolating, or both? My "gut feeling" is that I should be using pure extrapolation based on velocity. State change is received by the client, client computes a "predicted" velocity that compensates for lag, and the regular physics system does the rest. However, it 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.

  2. When a packet arrives, I've tried interpolating the packet's position with the packet's velocity over a fixed time period (say, 200ms). I then take the difference between the interpolated position and the current "error" position to compute 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 it'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 the concept fundamentally flawed, or is it correct but needs some fixes / adjustments?

  3. What happens when a remote player stops? I can 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 previous state - the physics engine has no way to say "you need to stop after you reach position X". It simply understands a velocity, nothing more complex. I'm reluctant to add the "packet movement state" information to the entities or physics engine, since it violates basic design principles and bleeds network code across the rest of the game engine.

  4. What should happen when entities collide? There are three scenarios - the controlling player collides locally, two entities collide on the server during a position update, or a remote entity update collides on the local client. In all cases I'm uncertain how to handle the collision - aside from cheating, both states are "correct" but at different time periods. In the case of a remote entity it doesn't make sense to draw it walking through a wall, so I perform collision detection on the local client and cause it to "stop". Based on point #2 above, I might compute a "corrected vector" that continually tries to move the entity "through the wall" which will never succeed - the remote avatar is stuck there until the error gets too high and it "snaps" into position. How do games work around this?

Tweeted twitter.com/#!/StackGameDev/status/85640009335574528
Source Link

Movement prediction for non-shooters

I'm working on an isometric (2D) game with moderate-scale multiplayer - 20-30 players. I've had some difficulty getting a good movement prediction implementation in place.

Right now, clients are authoritative for their own position. The server performs validation and broad-scale cheat detection, and I fully realize that the system will never be fully robust against cheating. However, the performance and implementation tradeoffs work well for me right now.

Given that I'm dealing with sprite graphics, the game has 8 defined directions rather than free movement. Whenever the player changes their direction or speed (walk, run, stop), a "true" 3D velocity is set on the entity and a packet it sent to the server with the new movement state. In addition, every 250ms additional packets are transmitted with the player's current position for state updates on the server as well as for client prediction.

After the server validates the packet, it gets automatically distributed to all of the other "nearby" players. Client-side, all entities with non-zero velocity (ie/ moving entities) are tracked and updated by a rudimentary "physics" system - basically nothing more than changing the position by the velocity according to the elapsed time slice (40ms or so).

What I'm struggling with is how to implement clean movement prediction. I have the nagging suspicion that I've made a design mistake somewhere. I've been over the Unreal, Half-life, and all other movement prediction/lag compensation articles I could find, but they all seam geared toward shooters: "Don't send each control change, send updates every 120ms, server is authoritative, client predicts, etc". Unfortunately, that style of design won't work well for me - there's no 3D environment so each individual state change is important.

  1. Most of the samples I saw tightly couple movement prediction right into the entities themselves. For example, storing the previous state along with the current state. I'd like to avoid that and keep entities with their "current state" only. Is there a better way to handle this?

  2. What should happen when the player stops? I can't interpolate to the correct position, since they might need to walk backwards or another strange direction if their position is too far ahead.

  3. What should happen when entities collide? If the current player collides with something, the answer is simple - just stop the player from moving. But what happens if two entities take up the same space on the server? What if the local prediction causes a remote entity to collide with the player or another entity - do I stop them as well? If the prediction had the misfortune of sticking them in front of a wall that the player has gone around, the prediction will never be able to compensate and once the error gets to high the entity will snap to the new position.