My turn (part 1)

Unity has all sorts of automatic support for networking.. as long as you’re looking to build a real-time game where your objects automatically synchronize across all your clients from a single controlling host.

Things get a bit more difficult if you’re trying to make a turn based game.

Altair is such a game. Players submit turns by clicking the end turn button which queues up the commands until everyone has completed their turn. Once all players have completed their turn, a signal gets dispatched to go along and collect all the commands and drop them in to the turn processor.

This part is actually pretty elegant. It leverages strangeioc’s signalling mechanism to fire off an EndTurnSignal  of which there could be any number of listeners. The signal is dispatched synchronously to all listeners and each listener is passed a list object to populate with whatever player commands they wish. Once every observer has had its turn to do what it needs to do, an EndTurnCommand is dispatched which takes the command list, fires it into the bound turn processor and actually calls the Process method accordingly.

So this works great in a single player setup (and is wonderfully disconnected I might add), but things start to break down when we want to have this work over the network.

Each player actually has their own unique view of the game world. Why? Because each player is going to have the ability to scrub back and forth over the turn history so they can see what happened from any angle at their own pace.

This presents an interesting challenge as we are no longer able to leverage most of Unity’s automatic synchronization magicks. If we did, everyone would see what the host sees and that’s not the point at all.

selected ship + movement ui overlay

So what do we do?

Honestly, I’m still sorting it out. I’m working with the idea of simply serializing the command list across the network as required but Unity won’t serialize any complex classes. The list of supported types pulled from the docs is:

  • basic types (byte, int, float, string, UInt64, etc)
  • arrays of basic types
  • structs containing allowable types
  • built-in unity math types (Vector3, Quaternion, etc)
  • NetworkIdentity
  • NetworkInstanceId
  • NetworkHash128
  • GameObject with a NetworkIdentity component attached

Note how it doesn’t even accept classes of any kind? Structs only! No lists either, arrays only!

My current approach is to create a custom network view of each command in struct form to enable serialization across the network pipe. I think this is a good thing as it will actually force me to think about what really needs to make that jump. It is however going to require a bit of extra work as I am probably going to have to implement my own id system (of which I’ve already mostly done anyway) in order to keep track of the game state.

Wish me luck!

Tune in next time for part 2 of this post.. In which I will hopefully have an actual working multiplayer turn processor!

Leave a Reply