Advertisement

server-side prediction...

Started by July 11, 2002 03:21 PM
9 comments, last by shurcool 22 years, 6 months ago
edit: this post was confuzing many people, so i tried to explain it again a little better and shorter. please read the 5th reply by me, i hope it clears up some things. we're making a 2d action game, with really fast moving players (propelled by weapon recoil and explosions) and all-speeds weapons. meaning will will have both slow moving weapons (which are easier to implement online) and instant (or almost instant) hit weapons. as a reference, i've read a lot articles about half-life networking. but this topic is still not clear to me: server-side prediction. there are two possible ways to implement it, that i can think of. one. the server, knowing a client's latency, predicts where the player would be at the time it receives a packet and extrapolates it. so if a player is moving in a somewhat straight line, the positions of that player on his machine and the server should be almost identical (and a small extrapolation error if the client is not moving such a linear trajectory). two. don't do it. just let the client's position be his latency in the past. that means that if there's a high ping player which is standing still untill another client fires a fast moving weapon, and only then (when the weapon is fired) he starts moving to the side. in that case in his local prediction his position will be such that the projectile would miss, but by the time his "move me to the side" packet gets to the server, the projectile will already have hit him. you might think that method two is worse because to all other players your possition will be (that_players_latency + your_latency) in the past. this is not true. that client, knowing his own and your latency times, will be able to correctly predict your position, and correctly display it (more or less so) on his screen. therefore, that clients instant hit weapons will be aimed correctly without the need to "lead the target". oh, and your own position prediction will also be handled properly: starting with the latest world state update (which includes your own position) from the server, keeping in mind that the position is your_latency * 2 old (why? because it has to travel there, be processed, and back... so it's a round trip), and using the strored key presses which are newer than that date, find out the final position which is used for rendering. note that this medthod is identical to that of half-life, and some basic pseudo code would look like so (in case i didn't explain this part well):

start with last authoritative update the server sent to us
for ( each movement that is time stamped after the movement that
preceded the state update )
{
    run the movement on the client and predict our new player
    origin;
}
set the final origin as the render origin for this frame
   
i searched around and couldn't find much articles on this topic, so link to such peices of information, or just your own suggestions would be greately appreciated (it's ok to propose a method three! ). thanks in advance, shurcool ps. the half-life networking article that i refenced to can be found here. i read more articles about the topic, but i found this one to be the best (and more thorough) of them all. --- shurcool my project [edited by - shurcool on July 16, 2002 1:58:36 PM]
each method has a major flaw.

low ping players get slight advantage if you dont back extrapolate depending latency (ie quake3). this makes sense, since the server goes by what is sent. you need to lead targets with instant hit weapons. its up to the client to extrapolate properly, and the server does not attempt to fix latency by any large measure. pushlatency as a client side varible helps control extrapolation client side.

the scenarios:
high ping fires at low ping. high ping player must lead target to adjust for his own lag. leading is much greater and there is a chance that the low ping player changes direction between packets for the high ping player. this is why instanous changes of velocity dont happen in most games, to help minimize the problem. no matter what, quick changes in momentum and direction require more updates.

low ping player fires at high ping player. low ping player may see some "warping" of the high ping player due to wierd extrapolation errors from having fewer updates of the high ping player. the low ping player does not need to lead as much since he needs to only compensate for his own lag which is lower then the high ping player.


high ping players get an advatage if you do back extrapolate (ie hl). dont need to lead, but now a low ping player can hit low ping players since estenially you "trust" the high ping player. this extrapolation will very likly be off since the low ping player had more updates of the world while the high ping player has missed some.
example:
he high ping player fires at the low ping player. the server back extrapolates. since the high ping player missed some upates, this error will now be applied to the low ping player. the world is sent back in time to where the high ping players world was (even though other low ping players are no where near that) and registers a hit (since the high ping player aims at the interpolated "ghost"). now the low ping player sees what he thinks is correct (when its not), and the high ping player gets ripped backwards through time since he was not even in that position when the hig ping player shot and already moved, but due to extrapolation this is not taken into account. instead a hit is registered, and the low ping players position adjusted accordingly. futhermore, the low ping player could not even react to the shot by the high ping player because it actually will (from the servers eyes with extrapolation) happen after the low ping player has moved. so history is changed so to speak. personally i hate that (ie around a corner to just be pulled back due to a high ping player shooting you).

other sceneario. low ping player fires at high ping player. low ping player fires at the correctly updated last known position of the high ping player, extrapolated based on trajectory. just like the high ping player. but now the shot will be registered in the future for the high ping player. thus things are moved forward in time now, and the extrapolation will cause the low ping player to miss. since the high ping player is given benefit of the doubt and allowed some grace time (ie extra latency extrapolation error). the lower the latency of the players, the less error that occers, and the better the system will work. unfortunatly low latency players need such little extrapolation adjustments by the server, the "normal" method (ie the one above iwthout server side extraoplation) will work just the same. once players above a certain ping (like 190 or so from my expierence) start to play, things get wonky from my perspective as a low ping player.

warping is an issue with both styles because if the player does not egt enough updates, and extrapolation has erros in it. players positions need to be adjusted. its worse when the server performs back extrapoltion of network data because players could be moved somewhere else due to a player player interaction being resolved many milliseoonds after it occered (over half a second for players with an average ping of 200).

this is why i hate cs (uses hl system, i mention this because some ppl actually think cs is a seperate game). you fire your weapon adn low ping players need to trail high ping targets a bit due to extrapolation erros that the server will make. this can also causet he famous "he is right in front of me and i fired full auto but missed completely" scenario, because a low ping player dont get the same benefit as the high ping player when the server back extrapolates.

a back extrapolation system does not mean the client can correctly show things. remember, the low ping player will not get the high ping players data when he is shooting, this the low ping player will be behind by the high ping players ping*2+his own latency. while the high ping player will only back by his own ping times 2. since in all player player interactions go back in time, lowpingers get the disadvantage of being held to the highest pinged players world due to back extrapolation. a great way to "even" the playing field by giving the high ping player the advantage instead of the low ping player since there are more modem players. another funny problem to be careful of are clients that purposly increase latency for a small interval to enhance the server back extrapolation and get easier hits (since now the server is back extrapolating so much using that client as the base ppl are almost standing still). this was a problem with early versions of the new hl netcode, and has somewhat been fixed (i think they just capped the max back extrapolation time).

so becareful which method you choose. each is flawed, but at least method 1 dont give an unfair and silly advantage to low ping players. because after all the low ping player will get wrong updates since the server back extrapolates:
player 1 shoots on packet x
player 2 is at packet x+4
server recieves shoot on packet x
sever back extraolates now all packets above x effectivly become moot
hits register, now player 1 is updated with packet x+5
player 2 gets a new extrapolated position based on the hit
player 2 falls off the roof since the hit nudged him enough
player 2 cant change his trajectory since the original one borught him to the edge
player 2 could have avoided the fall if at packet x knew a hit was going to be registered
unfortunatly the server dos not allow player 2 to redo his movement choices from x to x+4


seeing the fundamental flaws of the hl netcode?
Advertisement
i see what you have to say, but there isn't a possible way to make a mutiplayer game smooth as long as there's latency involved. there's no way another client can know that someone shot at him untill that packet arrives. there's no way around it. the only way is to make it "appear" smooth, and try to make the game fair for all pings as much as possible. so all methods are doomed, yes. but what i'm looking for is the best medthod to do it.

besides, in my game (it's a side-view 2d action game with worms... sort of like Liero if u know what that is, or worms armageddon but in real-time), player velocities will be very smooth, and won't change much a short amount of time. the only times when it might be a bit instantatneos is when your motion would be explosion driven. but i'm sure that by the time that explosion takes place, a packet notified that player x shot at xy at t and whatever, so that this client could know that explosion will happen in exactly 0.5 secs, and predict his own explosion-propelled movement, or any other client's with very little error (this all just theory).

on a side note, a similar argument was brought up here, and a rebuttal one to it can be found here. see if the 2nd one changes your mind.

oh, and about half-life networking being so bad, could you please name one fps game that would have a better networking system than half-life? i know that i haven't played q3 online, so i can't talk about that, but it seems to be that half-life has one of the best net systems of all the games i've played. but that might also be because the new games are more gfx-intence, and don't run as fast on my machine, so it might be just me (i have p3 500, but with a really good video card - Radeon 8500... the next best thing after gf4)... still.

so i understand that your complains towards my suggestions are all valid, it would be more useful if you could suggest a system that "isn't flawed" or is better. you don't have to discribe the whole thing, just say that game x has the best networking model and it works well why.

a person, thanks a lot for typing up such a long post, i'm sure that it took you a long time and i'm very thankful.

---
shurcool
my project


[edited by - shurcool on July 12, 2002 7:04:25 PM]
ok, why isn''t anyone replying? a week passed and all i got was one reply. why?

is my post too long and you guys are lazy to read it? is it because the title isn''t very appealing? why?

come on, this is like the most important topic in multiplayer for real-time shoot-em-up games! without prediction, you''d have to lead targets based on your ping!

can someone please tell me why won''t anybody help...

---
shurcool
wwdev
No one has replied because you seem to be doing this a little backwards. Normally, prediction is done on the client side, while the server remains the authority. Not too many have experience with trying to predict on the server side, so that''s why you haven''t gotten help. I''d have to see your client and server code, but I''d imagine it is easy to cheat, since it sounds like your server trusts your client (a big no-no in networked games)

Try making your server a totalitarian dictator, and do the prediction on your client.
fingh,
wow... if that's what all of you got out of my post (unless you just looked over in instead of reading it thoroughly, because of its size), then no wonder i didn't get any (except for a person's one) replies (which is good, because they probably wouldn't be helpful either).

i will read over my original post, and try to fix anything that looses you:

first of all, server has the complete authority over everybody , and doesn't trust the client at all. it only receives key-presses from clients, does physics, and sends the resulting positions back (for example, a client may send "i am holding down the 'move forward' key").

the client, on the other hand, predicts his own movement , which is corrected by server's sent out packets.

now, back to my question.

if i don't have any server-side prediction, then if client 0 has a ping time of 100 ms, then all his movement actions will be 100 ms in the past for the server (eg. he starts moving at 532 ms, but on the server he will only start moving at 632 ms).

ok, the problem is the following. if there's an explosion, which all clients (as well as the server) already know will happen at, let's say, 900 ms. the problem is that at those 900 ms, client 0 will be a certain distance away from that explosion, and moving away from it. but the server, will only know his position 100 ms (which is his ping time) ago! at that time, for all we know, he could've been right beside the center of it! but to him, those 100 ms after, it will appear as he is a safe distance away from the explosion. but since the server is the dictator here, he will tell the client that he was killed by the explosion.

the problem occurs because client movement is his ping time in the past, but the explosions aren't - they happen at the same time for all clients and the server.

so what should i do in order to fix that problem?

here's an example, which YOU DON'T HAVE TO READ because it might be long!

someone throws a hand-grenade which will end up at (0, 0) and will explode at 1200 ms.time is 1000 ms:client 0 is at (0, 0)he realizes that he has to get out of there, so he starts running awaya packet [move right] is sent to the servertime is 1100 ms:server receives that packet, and puts the client at (10, 0)client sends another packet [move right]time is 1200 ms now:server gets the [move right] packet again, and puts him at (20, 0)the explosion happens on both the server and the client, BUT!by this time the client is aready at (30, 0), safe from the explosion radius... or so the client prediction tells him!because on the server he is only at (20, 0), he gets killed (his life was low)!but to the player that looks like total bs!  
so how would i solve that problem?

ps. dammit! i wanted this to be a short, easy to read reply! :D please bare with me!

---
shurcool
wwdev


[edited by - shurcool on July 16, 2002 1:56:26 PM]
Advertisement
You are right, I jumped the gun and obviously didn''t read the original post thoroughly. Sorry about that.

There is a good paper that talks about this a little bit at
gamasutra.com: http://www.gamasutra.com/features/20010322/terrano_pfv.htm

The article discusses synchronizing events across clients and servers so that events occur at the right time. It may be helpful. If nothing else, it is an extremely interesting read (200 ms updates!). It is geared towards an RTS, but the concepts are still good.

The core of your problem is as much game design as it is game programming. In general terms, make exact position a little less important. Make attacks less definite on the client side (e.g. a bullet is visible coming out of the gun, but not necessarily hitting a target in the distance). Because you are proposing such a high pace game, perhaps your own option number 2 is best, or just make it a LAN-based game, not Internet.

in a scroched eart, worms, etc game where only a single player can do stuff during a turn, which method you use is irrelevent.

also clients tend to send vectors instead of key presses. this allows the server to do forward extrapolation and thus in your example the player would not get hurt at all. since the first update would cause the movement adn acceleration to start, the next packet confirms the player wishes to continue the course, during that time (ie between 1st and 2nd packet) the server is already accelerating the player, thus the next packet will let the server to know if the player slowed down at all or kept at moving. if the player slows down the server slows him down, not adjusting previous data. thus the slide effect you get when you have a large ping.

back extrapolation as you suggest harms low latency players and gives them false info since they get data which is correct, but the server later invalidates. thus they will be shooting at ghosts. alos they will be affected by things that occer in the past. you have to be careful about trusting a players latency. he could be using a proxy to drop or delay packets to help his game or even using bad network settings to get the ping advantage at certain times. hl had this problem (and to a degree still does).

you cant help high ping players without ruining the game for low ping players. also if you require such low latency to play, then require a broadband or lan connection to play the game.

most articles tend not to mention the real world effects of the back extrapolation because it looks so good on paper. in practice it was the worst thing valve did to hl. heck, not sure if you remember the revolt against the new netcode back when it was introduced. most players hated it. they were the low latecny ppl, now modem players have the edge.

players are already used to leading shots according their ping. cubic extrapolation (no game uses linear extrapolation anymore) is pretty accurate and is the same thing you would have problems with going backwards. thus introducing error twice (once by the client extrapolation and now by the server extrapolating backwards from its possible forward extrapolation to give updates to the other players who can keep up with the server).

bottom line, never lie to the clients. if you sent packets saying they were not hit. DONT go back a few updates to see if some high latency person actually scored a hit. that just invalidates updates and now the client cant even trust the server. so the server trusts the client more (ie assumes the latency and packet loss is not a lie) and lies to low latency players (since at anytime the server could say "oops, you remeber that update from 4 packets ago? well, actually i meant to tell you got hit instead of no attack occering at all").

its all a compromise. if the valve system worked well in practice, quake3 (and its brew of games) and ut (and its brew of games) would be using the same ideas. i think i trust id and epic a bit more then valve. heck id made the base of the engine for hl. id made 3 internet enabled mulitplayer games (4 if you count quake and quake world seperatly, and another if you want to count doom over ipx/modem/serial).

i played both q3 and hl. i also know i like the q3 network code much better and have had less wierd anamolies that caused me to be angry at the game and wonder how i got hit when i was already around the corner before the high ping player shot at me. i am a low latency player (ie on broadband).
Something you could try is delay the client side actions.
Form exemple if you have a 200ms delay :

Client A press the forward key a time T. You save this input and send it to the server with the timestamp T+200.
At T+200, client A processes the input.
If the client has 100ms ping with the server then the server will receive the packet a T+100. He have the input 100ms in advance and don''t have to predict any state.
The server can process the logic and even send the result at T+100. Your other clients will receive the packet at T+200 (with 100ms ping also) just in time to display the action

For the delay you have to test with your game design but i made a football game playable only on internet for my company and with a 200ms delay between key press and process of action it isn''t noticable.

Kucek
quote:
Original post by a person
you cant help high ping players without ruining the game for low ping players.



i don''t think u quite understand this part.

in quake, which has no backward extrapolation, therefore all your shots actually happen your ping time later (so you have to lead your target), low ping players get the advantage. because their bullets actually do damage faster, and they have to lead the targets a lot less (if at all). but high ping players have to lead their targets a lot more, putting them in a disadvantage.

if we were to use a backward extrapolation system, no one would have to lead their targets. therefore low ping players don''t have the advantage anymore. that makes them think (and you too) they they''re in a disadvantage now, when actually it is just equal for all. but even that is not completely true, LPB still have an advantage (but a much less major one) - their prediction of other players is more accurate (especially if other players are of a ''jumpy'' nature). this causes another problem, when a HPB shoots a LPB, LPB will not know about it until the "i shot" packet from the HPB will get to the server, and then to the LPB (that, obviously, happens a lot faster). that makes him think that he was teleported back in time and hit.

both of the systems have their pros and cons. quake chose the no-back-extrapolation system because the game is more of a fast paced nature, where leading targets is more acceptable. on the other hand, half-life though it would be more realistic not to lead targets, so they went w/ the backward extrapolation system.

this is the last time i''ll explain it, and i know that it''s very annoying to be a victum of "a shot around the corner" where "you get sent back in past and get hit".

Kucek, your suggestion might be appropriate for my game, because of the slow acceleration speeds. i might make the delay in movement a little less than 200 ms though, but the concept stays the same. this might also apply to shooting (but a much less delay in shots is required for a smooth gameplay) too.

another problem arises because when you shoot someone, they will be sent back flying in the opposite direction. it is possible to predict such rapid direction change only if the client is 100% sure that the weapon it just fired at the target will definitely hit it. and that''s not even it! because the terrain is destructable, when a client shoots the projectile might hit the target, but when the packet informing about the shot gets to the server, land might be modified (added) which would block the projectile from hitting the target. thus no hit is registred, but your client predicts the target to be hit (and fly in a different direction), which will cause some really bad warping on your target. if we could only trust the client, none of these problems would arise... *damn hackers!* i''m thinking maybe of a way to confirm a client''s hit on the server... :-|

---
shurcool
wwdev

This topic is closed to new replies.

Advertisement