When Richard told me that he needed “a Riker to my Picard to bring this project over the line”… well, how could I say no? Ever since I first played Metal Gear Solid 2’s demo I have been obsessed with gaming, and felt like I should attempt to make something. Since graduation in 2017 I have worked in software development. Experience as a programmer and later consultant allowed me to hone my skills, but recently, as everything certain has become uncertain, I felt it was time for a change.
With online multiplayer games it is important to make sure each player remains ‘in-sync’ with others at all times. This is where the Lockstep protocol comes in, it ensures that all players see the same actions taking place at the same time (within milliseconds depending on latency). Richard had already started implementation using John Pan’s lockstep framework, but it needed work.
During my first month this is where I focused, after spending a few days getting to grips with the codebase and Unity itself. My technical background was C# for web applications, so I knew the language, but the architecture was mysterious; much like the title of this post (a reference to one of the greatest movies of all time.)
After preliminary analysis the code looked abstract, all too abstract. So I began to, well, ‘rip out’ wouldn’t be far from the truth, lots of files I felt were unnecessary. Once I got the project building again I re-organised the classes into a legible folder structure. One thing to note here: If you’re going to move classes about, do it in the Unity editor, so that script references are not lost to game objects.
Once I was satisfied with a first pass it was nearly time to test. However, I had a few issues with the lobby and network code. For a start, players were not able to click the ready button to start the game. This proved to be a simple fix as the system was not treating joining players as humans.
Next task was to play a game, and to begin the cube wars. I discovered that the system was treating every spawn command as if it came from the host, this was easy enough to fix. But then it seemed that actions, whether to spawn a unit or move, were not reflected on the other players’ screens. This was somewhat problematic, had I missed something in the refactor? An investigation had to be carried out.
I began by taking it back to basics. I stepped through every line of code, from the spawn command until the unit appeared on-screen, I then compared the path the code took to other classes that I thought were relevant, in case there was a call to a secretive method. This was not the case.
My main mistake was assuming that the commands were being sent between players, examining code which looked very much like it received data packets. After a few days, and the odd existential crisis, I had a cup of tea and prepared to continue my war with the network code.
The entire British Empire was built on cups of tea. And if you think I’m going to war without one, you’re mistaken.Eddy (Lock, Stock and Two Smoking Barrels)
Fuelled on tea and biscuits I had another crack at the code. I created a ‘SendCommandOverNetwork’ method which utilised Unity’s NetworkTransport class. Suddenly I was able to send spawn commands. “It’s all completely chicken soup” as Tom would say.
Now I could finally get to testing. I had to be sure that commands were being executed by all players at the same time. Move commands had to take a similar amount of time to process and act upon, as this would be an easy way for players to become ‘out of sync’. I believe simple solutions are the best, so decided to log data to a .txt file, revealing critical information, like who sent the command and how long it took to execute.
I compared the logs, finding that one game was at least four seconds faster than the other. Yes, seconds, not milliseconds. Even after logging more data I was still not any closer to a solution. I then wondered, what if the Unity editor is just faster than the game builds? In hindsight, it did seem like an unfair test, to have one game build and the other within the Unity editor. So I changed the logging slightly, and had two game builds logging to separate files. You can already guess what I discovered, not only was the time of execution the exact same but the calculation times were pretty much equal, give or take a few milliseconds.
My first month was good, but I struggled with a few of Unity’s nuances, learning harsh lessons in the process. The transition from consultancy to working with a start-up on a game has been interesting. Work no longer feels like ‘work’, bugs are welcomed as a challenge to overcome rather than with distain or fear of missed deadlines. I am looking forward to the next challenge, which is of course more lockstep features regarding building, stances and overclocking.