Download

Multiplayer: how to make sure a client executes animations in the correct order?

This is a purely conceptual question that is related to both C++ and Blueprint programming.

Introduction
Imaging we have a usual multiplayer game, where the server executes most of the game logic and sends state to clients.
There are two options for sending state from the server to clients:

  1. Replication. We mark certain properties as replicated. When these properties change, the changed Actors are queued and, eventually, the changes are sent to the clients. By “eventually” I mean we have no guarantees the properties are replicated in any particular order. At the end of each tick, the engine looks for changed Actors to replicate, but it can discard certain Actors because they were replicated recently and can wait for several frames. Besides, even Actors considered for replication are sorted by priority and starvation. While the priority is something I can control, starvation depends mostly on the network state and Actor update frequencies. Source. The bottom line is that I don’t know the order of property or even Actor replication. It is definitely not the same order I have changed the property values. For replicated properties, I can define RepNotify callbacks to play animations when the client sees state changes.
  2. RPCs. RPC is sent over the network at the very place it is called unless it’s Unreliable Multicast. Source: NetworkDriver.cpp: UNetDriver::ProcessRemoteFunctionForChannel() . This means that reliable RPCs are actually ordered and the order is the same as the call order. On the downside, they don’t record changes in game state (like a player joining the game later has no way of getting older RPCs), they are heavy on the network and the docs advise to use replication when possible. What is even a bigger problem is that RPCs usually happen before property replication, so even if the state was updated on the server before RPC call, when the client executes that RPC it sees the older version of the state.

Given that during RPC execution on the client I don’t have enough up-to-date state (what means the player still SEES older state) to play animations correctly I have to rely on Replication anyway.

Problem
To play animations on a client in response to changes on the server I have to use Replication + RepNotify. Property Replication has no particular order, so I cannot control the order in which RepNotify handlers will be called and thus the order animations on the client will be played.

Questions

  1. Is Replication + RepNotify a proper way of implementing animations on clients in response to server actions?
  2. If Replication + RepNotify is the thing, how to ensure a client plays animations of different Actors in the correct order? Like I want a Character to first enter the area with a bomb and only then blow the whole thing up.
  3. If there is no way to ensure animation order, do you just rely on the whole system to be fast enough so the player doesn’t notice anything?

Let’s not consider simulation that clients do to predict the server’s state because it’s a completely different beast and it complicates the matter.