Jump to content

  • Log In with Google      Sign In   
  • Create Account

Client/server movement when to update?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
11 replies to this topic

#1 Valoo   Members   -  Reputation: 403

Like
0Likes
Like

Posted 26 June 2013 - 01:36 PM

Hi,
for my multiplayer game i implemented an interpolation/extrapolation mix for movement sync.
It works very well between source and server. But i'm not sure when i should update the clients about changes.
For now i would just reroute the source packets while also simulating on the server (for validations and so on).
But that means the more players i have the more movement packets i will have flowing around randomly.
I thought about packing the movement data of all players in a bundled packet and distribute that in certain intervals. But wouldn't that mean i have to sample the data from the simulation on the server? Also, MoveStart and MoveStop packets are sent instantaneous to aid the extrapolation and those would look odd if they didn't arrive until one of those intervalls, i guess. Am i wrong?
What would be the best approach for this?

P.S. i target around 20-40 concurrent players online at max, movement packet size with header is around 25bytes, 3 times per second

Sponsor:

#2 hplus0603   Moderators   -  Reputation: 5693

Like
0Likes
Like

Posted 27 June 2013 - 11:29 AM

You should pack up all movement commands from players for simulation step X, and send them all together in a packet. You can pack up commands for steps X through Y and send them all together. As long as the clients know what step numbers have what commands, they can play it back correctly after receipt (with some latency.)


enum Bool { True, False, FileNotFound };

#3 Valoo   Members   -  Reputation: 403

Like
0Likes
Like

Posted 27 June 2013 - 01:08 PM

thank you for your reply. You mean, i should take the positions from the simulation on the server? Or have a certain interval and combine every actual player input that arrived in between two timesteps? I dont have a replay/rewind system, if you implied that and i dont think i would be able to implement that. i had a hard time even implementing the interpolation/extrapolation.

#4 hplus0603   Moderators   -  Reputation: 5693

Like
1Likes
Like

Posted 27 June 2013 - 02:15 PM

combine every actual player input that arrived in between two timesteps?


I am suggesting all your clients run physical simulation at the same number of steps per second as the server. Further, I am suggesting that each input is intended for a particular time step, both on the client, and on the server. This, in turn, generates a strict ordering of events, and as long as that strict ordering of events is maintained, then everybody will see the same thing.

An alternative is to send a snapshot of the server position and velocity for each player, for each network step. This means that different players will see different things. That may be OK for your game. You may even run simulation at different speeds on different machines -- Quake II did this IIRC. The draw-back there is that you'll have problems like certain ledges can only be reached by jumping if your frame rate is at least 100 fps or whatever.
enum Bool { True, False, FileNotFound };

#5 Valoo   Members   -  Reputation: 403

Like
0Likes
Like

Posted 27 June 2013 - 04:22 PM

Sorry, no offense,
but i think i dont really understand you. I dont need a synchronized physics simulation. And i dont understand the 'intended for a particular timestep', like 'no, you should not press jump right now'?
The events i need (MoveStart, MoveUpdate, MoveStop) are in the right order if that's what you mean. I also send them ordered (Lidgren reliableOrdered).
For now, if i just instantly reroute the movement updates, the interpolation on each client looks very smooth. I'm just concerned about the amount of packets this generates and so whether it's a good or bad idea to have a fixed interval at which i sample the interpolated movement on the server and instead distribute that.

For the different speeds on different machines. I use Unity and try to relate everything that needs it to the deltaTime, so it should be the same on each client.

(I'm not a professional programmer, so i may have used certain terms in the wrong context, but i hope it can still be understood; english is also not my mothertongue)

But maybe i should just test each option to see myself.

Thank you for your help so far.

#6 Dave Weinstein   Members   -  Reputation: 532

Like
1Likes
Like

Posted 27 June 2013 - 04:54 PM

Send MoveStart and MoveStop the frame they happen. Limit MoveUpdate to a 10hz frequency. Combine all movement updates sent in a given frame into one packet.

 

That should give you decent baseline performance, and you can tune from there.



#7 hplus0603   Moderators   -  Reputation: 5693

Like
0Likes
Like

Posted 28 June 2013 - 10:25 AM

I dont need a synchronized physics simulation


Really? Then why are you trying to do networking, instead of using a random number generator? :-)
That may be a funny way of saying it, but think about it for a minute. The whole point of networking is to sync the view of a shared simulation across multiple players.
enum Bool { True, False, FileNotFound };

#8 Valoo   Members   -  Reputation: 403

Like
0Likes
Like

Posted 28 June 2013 - 12:13 PM

It's just, i guess you were trying to give me ideas for the general 'how to make it behave as you want'.
But i didn't and still dont understand it. Maybe it's because i'm not knowledgeable enough about general game/-engine concepts to apply to my game what you said (i only know Unity/c# and this is my first online multiplayer game). But i think i will try what Dave Weinstein suggested and separate/combine certain updates (that answer was simple enough for me to understand :-P )

And maybe it's also because of the way i implemented the movement sync, i cannot say if it is the right way to do it, i developed it all by myself by trial and error.
Whenever a MoveStart or MoveStop packet arrives, i clear the (2 packet sized) buffer and rebuild it by calculation (interpolate from currentInterpolated to current and set timestamp of the first rebuilt packet to lastpacketTime- 1x updateRate (only then it works)), else the movement would look discontinuous.
For the MoveUpdate Packets inbetween (because they happen in regular intervals) it looks perfectly fine without intervention.
I guess the question in my entry post relates to that behaviour, as i wasn't sure how i should hold the MoveStart and stop packets back (until the new server-send interval) without breaking the movement simulation.

Is it common to help the interpolation with such a recalculation or did i just not implement it correctly?

P.S. The simulation you talked about; i'm confusing simulation with simulation because i feel that the movement here is not 'simulated', more like 'predicted/given'. Just another example of me not knowing how to communicate effectively :-P

#9 Herwin P   Members   -  Reputation: 645

Like
0Likes
Like

Posted 29 June 2013 - 09:44 AM

I think what hplus0603 means is to make your client to predict the movement by itself while waiting for an 'approval' from the server. Like, when a character moves to a coordinate with a particular speed, the client sends a message (I'm walking to this direction) to the server and also does the walking animation by itself while waiting for a reply from the server (you will hit a wall in this direction). The server checks if the character's direction is clear or not, and tell the client so the client can know if the character will collide to something or not.

 

Clients                                  | Server

One clicks move                    | Waiting

Sends message to server      | Waiting

Plays walking animation         | Gets the message

Still playing the animation      | Broadcast the message so all clients can know that one is moving

Still playing the animation      | Checks for collisions

Still playing the animation      | Sends the information to all clients (meets a collision for example)

Gets the collision message    | Waiting

Stop the movement                | Waiting

 

While it looks like the client is waiting too long, it is not. The client moves by itself while waiting for an approval from the server. If the latency is too high, the character may walk through the wall and suddenly jump back to a position before it hit the wall. If the character doesn't hit a wall, it will keep moving until it reaches its target. If your clients don't play the animation by themselves, they will need to wait for a short period of time before the clients play the animation.

 

This way, all clients will be aware of each other's movements. I think that's what hplus0603 means with synchronized physics.

 

I apologize if that's not what you mean and I interrupt the discussion.

 

As for how often you must update, I think Dave Weinstein and other people can answer it better.



#10 Valoo   Members   -  Reputation: 403

Like
0Likes
Like

Posted 29 June 2013 - 12:16 PM

Thanks Sky warden for taking the time help. Basicly what you described is what i'm already doing, i'm just not sure if how i do it is right, because i kind of fake certain inputs to correct the simulation which would otherwise break. Plus the way i send the packets seems unefficient because i reroute inputs the second they reach the server which i guess will possibly flood the server once it reaches a certain amount of online players.

#11 hplus0603   Moderators   -  Reputation: 5693

Like
1Likes
Like

Posted 29 June 2013 - 03:12 PM

It still sounds like you're not using a proper fixed time-stepped simulation.
Your simulation will be pain and cause bugs if you don't do that.

Here's the simulation loop on the server:

stepnumber = 0;
forever() {
  input = empty_set();
  while (!clock_is_time_for_step(stepnumber+1)) {
    keep_collecting_input(input, stepnumber+1);
  }
  step_state_from_to(stepnumber, stepnumber+1, input);
  send_updates_to_players(stepnumber+1);
  stepnumber += 1;
}
Here is the simulation loop for the client:

#define HALF_RTT 5 // or whatever
stepnumber = 0;
forever() {
  input = empty_set();
  while (!has_received_server_packet_for_step(stepnumber+1)) {
    keep_receiving_input(input, stepnumber+1);
  }
  step_state_from_to(stepnumber, stepnumber+1, input);
  render_state_to_screen();
  send_update_to_server(stepnumber+1+HALF_RTT, read_keyboard_and_mouse());
  stepnumber += 1;
}
Note that they are very, very, similar! The main difference is that the server receives commands and sends out collected state/commands, whereas the client receives collected state/commands and sends user input for some future step. Also, the client is driven by the server's packet rate, whereas the server is driven by an actual clock.
enum Bool { True, False, FileNotFound };

#12 Valoo   Members   -  Reputation: 403

Like
0Likes
Like

Posted 30 June 2013 - 01:19 PM

I'm about to get an understanding. Your example is very good. I'm just having difficulties translating it to my code.

is stepnumber an actual number i increment or Time? If number, would that mean, it is only incremented on changes/in an interval?

 

You are right, i'm not familiar with this fixed timestep concept. I guess that's why some things break when i build my code on top of that missing base.


Edited by Valoo, 01 July 2013 - 06:05 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS