Prediction in an online multiplayer game with an event manager

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Prediction in an online multiplayer game with an event manager

      Hi, how would you handle prediction in an online multiplayer game with an event manager, such as in GCC? It seems to me that it would not be as simple as forwarding the same events from client to server and vice versa. So client logic and networkforwarder could both subscribe to PositionEvent(), but it looks like they will soon go into strange loop. Does this mean you need to have two separate events for predicted position and real/corrected position? Or perhaps a field indicating whether this is a prediction or a correction event? The problem once again is that Server and Client emit the same events, and they both have logic and networkforwarder subscribed; listening for those events. Have a look at this picture to understand it better. Any thoughts on this?

      Client sends out new PositionEvent() (in green). PredictedLogic and NetworkForwarder get this event and do their respective things. After NetworkForwarder on Server side recreates the event it send it to the real logic, but mistakenly also send it to it's NetworkForwarder since it's also subscribed (this is the loop).

      Real logic then creates a correction event (in purple) and send it out to the event manager, which then forwards the event to NetworkManager and Server's Real Logic again... You see where this is going. :wacko:
    • A few days ago, I thought about how I would personally go about doing events for a multiplayer game.
      I think that it should be sufficient to just send the input of each player to every other player.
      If your event handling is deterministic, all players should have the same gamestate at every frame,
      assuming they always have the input of all other players.
      There might be a problem, though, with slower connections, and one would of course have
      to do something about this.
      But it certainly would be overkill to send every event from every player via the network.

      Another alternative would be to just send all input events to the remote server, have that
      server calculate the next game state, and then send the changes back via the network.
      That would make sure everyone has the same gamestate, but it would of course increase
      the workload of the network.

      I'd personally prefer the first approach, but I haven't really figured it completely out yet
      (e.g. what do you do if a player goes out of sync and has an outdated gamestate?),
      so it will be interesting to see how this develops :)
    • You need an authority. These days, that authority rests with a dedicated server that every connects to. If you load up Battlefield or Left 4 Dead multiplayer, you're connecting to that server just like every other player. In the olden days of Quake or Unreal Tournament, one of the players often acted as the host. The idea is the same though: you have one authority for the entire game state.

      This is really important for things like input/data validation to keep clients from cheating and for maintaining consistency. For example, I can run the same calculation on the same input data on two different machines and get two different results thanks to floating point precision errors.

      The other issue is performance. If every player is receiving input from every other player, it becomes a mess to sort it all out. And what about network latency? Say I launch a grenade at two players and an event is sent. On my screen, it looks like I should hit you but your computer has a position slightly outside the radius. Who's the authority?

      This is why there needs to be a server.

      I don't really understand what your original question is with regards to prediction. If you're just asking about not receiving an event multiple times, you can make the second version of the event a totally different event type.

    • Thanks for the feedback.

      @Rez Yep, I'm dealing with a client->server architecture, and I was hoping to implement prediction&correction with out creating a bunch of new events for every action that needs prediction. I guess I'm hoping for an elegant design that goes well with this quote from the book:

      "This event was generated on a remote machine, sent over the network, re-created from the bit stream, and put back together again just like Dr. McCoy in a transporter beam. Recipients of the event really have no idea it was generated from afar and sent across the Internet." -page 689
    • Looking at the graph, I see one important difference between the system I propose in the book versus what yours. In mine I never have the client send a position update to the server - instead I send something like "Move this direction at some speed". The server would receive this message and attempt to move the player, but the actual position would likely be somewhat different such as if the player's character were sliding along a wall standing in their path.

      The server would communicate the authoritative position down to the client at frequent intervals.

      But, the client could also perform the very same checks the server does, detect the same wall, and move the player in an estimation of the server's authoritative position to minimize lag and optimize bandwidth. The icky issue comes into play when you need to detect multiple dynamic objects (other players, rocket propelled grenades, etc.) and estimate their movements when lag gets higher than some threshold. In that case, the client would do its best to estimate those new positions. If a server update comes in and the client estimated with a degree of error, the client must then visually fix the problem, since a dynamic object would have to teleport to its actual position. Since teleporting looks really bad, a quick interpolation is the typical response.

      That's why sometimes in action games the rocket propelled grenade follows you around the corner and kills you anyway.

      Looking at your graph, the green arrow labelled "send prediction back...?" isn't really needed IMO. Instead, the "Prediction Logic" might best belong as a component of the Client View, ticking along and overriding position/rotation data only when the authoritative positions/rotations have gone AWOL for some reason. When the actuals finally arrive, the client view would then start a process to fix any visuals that have exceeded some error threshold.
      Author, Programmer, Brewer, Patriot
    • @mrmike Thanks for the excellent reply. This actually seems like a pretty big thing I've overlooked. So it looks like there are two type of events: Input and Output which all go through the server logic.

      Yep this solution makes me quite happy, and even though it uses two events to do one thing, it makes sense and I find it quite elegant.