Multiplayer Networking: Syncing Animal Movement

When I started multiplayer programming, I was not expecting to have too many issues with character movement. After all, nearly every game has moving avatars, so I expected built-in methods to have this covered.

But, of course, things aren’t that simple. Games vary wildly from each other, and the way characters are controlled can be fundamentally different. For example, a character controlled by key presses moves until the controlling key is disengaged; while a point-and-click character only stops moving when the destination is reached or the command is cancelled. The way these commands are processed is not the same.

Arborlands uses a point-and-click interface similar to a real-time strategy game; networking for this came with a learning curve for me.

Server as State-Keeper

When I first started learning Unity Netcode for Game Objects, what I gathered from my research was that the best model for networking was a server centric one. In this model, players – known as clients – communicate their commands to a central instance – the server – which keeps track of the game’s true state.

Initial server-as-state-keeper model

In this initial model, clients don’t actually affect the motion of game objects. Rather, they ask the server to make the changes. You can imagine this like four people playing a board game with only one person rolling the dice and moving the pieces for the other players – that person is the server. Much like the player who is moving the pieces and also playing for themselves, the server has a player instance that is participating in the game.

This model is very clean and prevents tricky cases where the clients might start losing track of each-others’ game state.

But, sadly, this totally doesn’t work for my characters’ motion. Maybe it’s due to me being a newb, or maybe this model is built for characters that are controlled by key-command. Either way, the result was not good.

Check out the video below – the server-side arborian is negotiating the turns correctly. But the client arborian slides and jitters on some of the turns.

As far as I can tell, this is happening because there are two different refresh cycles.

  1. The local cycle – which refreshes according to the system’s local time and frame rate
  2. The network cycle – which refreshes whenever a command from the network is received

The server only acts according to the local cycle and sends updates to the clients. The server fires-and-forgets the updates and doesn’t follow up with the clients to see if they got the message.

The clients, however, only update when they get a network message from the server. These updates are subject to network latency and are received at visibly varying intervals. This is what seems to be producing the sliding effect on the client side.

Change-and-Inform Model

To remedy this, I created a new model. I call this model “change-and-inform” because clients make their own changes to the destinations (of the character they control) and concurrently update the server about those changes. The server, in turn, tells the non-controlling clients about that new destination. Every instance then proceeds to move the arborian according to the new destination without synchronizing its present location with the other instances.

The assumption is that if the starting and ending location are the same and the processing of the motion is the same, then all instances will be perfectly synchronized.

The new model is slightly more complex and has desynchronization risks

This method creates very crisp motion for the arborians and actually reduces network traffic because only the destinations are updated across instances. The location and animation updates do not need to travel across the network because they are processed locally by each instance in accordance with the synchronized destinations.

There are some risks with this model: because the instances do not synchronize the actual location of the arborians, differences in arrival times of the destination commands could theoretically cause noticeable differences in location while in transit. However, thus far, testing has not revealed this kind of behavior.

In a subsequent networking post, I’ll go into why this model is not needed for the land and plants of Arborlands.

Thanks for reading!

Leave a Comment