Network Replication

Network replication

Starting from GC FSM v1.4, FSMs can be replicated over the network. The feature uses reliable RPCs to replicate state changes from the server to the clients. In order to replicate an FSM, there are a few pre-requisites:

  1. The context object must be an Actor (i.e.: either the FSM is defined on the actor itself or in a state class with Context variable of type derived from Actor);
  2. The context actor must be replicated;
  3. The context actor must have a GC FSM Replication Component;
  4. For a sub-FSM, that is an FSM defined in a state class, the parent FSM must be replicated as well.

If all pre-requisites are met, in order to replicate the FSM you simply set the “Replication Options” of the LaunchFSM node to “Replicated”.

The GC FSM Replication Component has to be added to the actor blueprint or as a default subobject in C++. This ensure the component is present as soon as the actor is spawned. Spawning a GC FSM Replication Component at runtime, after the actor has begun play, may not work as expected.

To launch an FSM as replicated, just select the LaunchFSM node and set the "Replicated" option in the detail panel.
The GC FSM Replication Component can be added with the "Add Component" button

What happens on the server side

When a replicated LaunchFSM is executed on the server for a replicated actor, an authority FSM is started. This FSM behaves identically to a non replicated FSM except that, additionally, all connected clients are instructed via reliable RPCs to also start and keep synchronized proxy FSMs on the proxies of the actor.

Whenever an authority FSM enters/exit a state, all connected clients are instructed via reliable RPCs to also enter/exit the same state on the replicated proxy FSMs.

Similarly, if an authority FSM stops, because it reaches a Stop node or a parent FSM made a transition, all connected cliens are instructed via reliable RPCs to stop the replicated proxy FSMs.

On the server, a replicated authority FSM behaves exactly as a regular (non-replicated) FSM. Blueprint nodes along a transition, such as "Do Something" are executed normally.

What happens on the client side

When a replicated LaunchFSM node is executed on the client, nothing happens. A proxy FSM is started only as soon as an authority FSM instructs the connected clients to do so. A proxy FSM behaves differently from a regular FSM.

First of all, a proxy FSM has a special “wait for commands” pseudo state, in which the FSM is not executing any state activity, but is simply waiting to synchronize with the server. When started, a proxy FSM is immediatly put in this special state.

When a RPC from the server is received saying that the authority FSM has entered a state, the flow of execution jumps directly to the specified state, without executing any other blueprint node. The OnEnter handlers of the activated state are executed normally and the state starts executing OnTick handlers.

Similarly, when a RPC from the server is received saying that the authority FSM has exited a state, the active state OnExit handlers are executed and the active state is exited, then the FSM immediately enters the “wait for command” state, without executing other blueprint nodes.

In order words, while the authority FSM on the server executes the blueprint graphs as usual, following the blueprint connections according to the triggered transitions, a proxy FSM on a client appears to be jumping from state node to state node without executing anything in between.

On a client, a replicated proxy FSM appears to be jumping directly from a state to the next. In particular, the "Do Something" node is not executed.

GC FSM supports hot-joining. This means that if a client connects after some time that the server has started, all replicated FSMs are recreated in the exact state as they are on the server.

Event triggering and processing

All event processing happens only in the authority FSM on the server. The proxy FSMs are synchronized only when the authority FSM enters or exits a state, or when the FSM stops.

When a TriggerEvent node is executed on the server, the event is triggered as usual in all FSMs of the effective target and possibly in all sub-FSMs, according to the specified trigger policies. However, when a TriggerEvent is executed on a client, the event is not triggered in proxy FSMs (the event is still triggered as usual on non-replicated FSMs, though). This ensures that the proxy FSMs are kept in sync with the server.