Today marks the day I begin implementing multiplayer with my game Crash. If you want to learn more about the game I’m making take a look at Introduction to Crash, but essentially it’s a realtime strategy game where you can code units yourself using Python to fight other programmers.
Up until now I have been developing the game single player however I kept in mind multiplayer up until this point and you can even emulate a second player so I hope those considerations will help me going forward.
Upgrading Unity
In order to help me with my development for multiplayer I upgraded the project to use the Unity 6.0.0 Preview. I know people have been pretty cautious due to the new runtime fee attached to this version but I don’t really think it’s a big deal for me at this stage.
However a really cool package that comes with the new version is the ability to create virtual players and spawn multiple windows with different configurations to test multiplayer really easily. You would usually have to install ParallelSync which is a package that helps you do this, but under the hood it just copies the entire project or you would build the game each time you made a change to test it.
Mirror
Next I installed Mirror which is a very popular open source networking project. Let me say that my experience with Mirror so far has been excellent. It’s just a few clicks to get the project setup with multiplayer and they provide you with a testing GUI.
Then all you have to do to setup any objects that will spawn is attach:
- NetworkIdentity
- NetworkedTransform
And then spawn these GameObjects through something like this:
NetworkServer.Spawn(unit.gameObject)
And you’re off! Just with this I was able to spawn in Units on both my Server and Client and they were all moving about perfectly fine. However, I’m interested to see what the latency will do to affect this game since I can have about 400 units moving in realtime.
Proposed Networking Flow
In my game these various assumptions can be made:
- Perfect accuracy and reliability of position for clients is not needed since the game client is simply a visualiser of where units are at that given time
- The server will handle all of the real game logic like hits, spawning, currency etc. this way there can be a single point of truth
In this way, there will be a very simple data flow:
- Clients will send any commands like
UnitMovementCommand(unitId: 232, dirX:0, dirY: 0)
direct to the server via a TCP protocol so nothing gets dropped - Server will receive said commands and handle turning commands into actions for the units and updating the game state
- Server will send out events for effects to be spawned and positions of the units
- Clients will spawn effects, move their units to line up with the server with some interpolation
However there are some other more complex issues I can foresee. The game itself runs on a tick rate which is the speed at which the Python code is communicated with and the speed at which the game data is send to the Python code.
However since the client will need to send their commands over TCP to the server, it could take upwards of 100ms to do so (worst case) this means the tick rate of the game needs to be increased to match worst case latency so that the client is not at a significant disadvantage but I’m sure this will need a whole post on its own.
P2P vs Dedicated Servers
This is another big decision to make when building a multiplayer game. P2P will make it so that cheating is pretty much unstoppable and we will have to handle the significant advantage the server player will have. However I believe for casual games where players are just testing their code against other players this will be a fine solution and as long as there is no ranking system it doesn’t make sense for players to cheat.
However, every month or so after the game’s release I wanted to run a tournament where for a few days I will host dedicated servers that people can connect to and vs each other for a ranking and some prizes.
Luckily this may not be so hard to do since Mirror supports setting up headless mode with the Server only option and it may be as simple as spawning a bunch of AWS EC2 instances and running the game on there (hopefully).
I’m more concerned about getting P2P working well since I don’t have the funds to run dedicated servers consistently, P2P still needs Relay Servers and Matchmaking servers for which I’m hoping I can leverage Steam’s servers through SteamWorks but I’ll have to look more into it!
It’s just Day 1 of Multiplayer and my head is already starting to spin, can’t wait to get into the thick of it. I’ll keep you all updated 🙂