Fluid Truck employees have a plethora of talents and interests outside of the scope of their Fluid Truck work. One example of this is Connor Swatling, Fluid Truck’s Data Analyst lead. While on PTO, Connor designed a whole computer game featuring a Fluid Truck – Fluid Runner! Keep reading to learn his process and play the game yourself.
Taking time off work gave me an opportunity to take on a new project, and I had definitely been thinking of giving game development a shot. I’d never built a full game, but had always been into modding existing games like Skyrim or clients like RuneLite, so the idea wasn’t completely alien.
That said, it’s one thing to build on an existing project, but another to start from scratch entirely.
Fluid Runner was inspired by the 2010 Adult Swim game, Robot Unicorn Attack, which fits into a category of video games called “Endless Runner.”
Endless runners like Robot Unicorn Attack, Temple Run, and SkiFree all feature similar mechanics. The player character is locked into forward motion on a never-ending (“endless”) level, with the player’s only form of control manifesting in their ability to destroy or dodge obstacles.
It’s a simple concept with a solid template to compare against, but it presented a gambit of new technical challenges that I could use as springboards for future projects.
In writing out my requirements document (the first step of any new project!) I focused on a few key areas:
- Animation – in-game elements, including the player’s avatar had to be more than just static images
- Asset collision – the player’s avatar needed to be able to conditionally interact with the environment
- Asset design – as many custom, unique elements as time allowed
- Environmental Triggers – the ability for elements of the game to change based on variables within the game setting
- Menus – thrusting the player right into the game on start is a bad user experience, so having a start menu seemed like a no-brainer
- Physics – some interaction with a physics engine to control falling, jumping, speed, etc.
- Score/points – what fun is a game without a way of keeping score?
The first part of building a game is choosing a framework in which to build said game. There have never been more options for would-be game developers to build their own content, and each has pros and cons so the analysis paralysis can be significant.
I already had some experience with the Unity engine from a college project so, to keep things simple, that was my choice here.
Unity’s primary scripting language is C# (“C sharp”). I don’t do a lot of development personally or professionally in the .NET framework, but C# is a very common language so I wasn’t very concerned with figuring it out. One of the best things about development is that if you bump into a problem, you’re probably not the first one.
Having outlined the scope and selected the engine, the most cerebral part of the job was done. As one of my professors used to say, “once you’ve planned the work, all you need to do is work the plan.”
Starting with asset design, I knew I really only needed five core objects:
- Avatar to represent the player
- Platforms to drive on
- Obstacles to impede player movement
- Opportunity for bonus points
- Backgrounds for flair
With one monitor showing Google Images and the other showing Adobe Photoshop, the process of creating game assets was underway. Some were pretty simple static images, like the background and bonus points. The others were more involved.
It was around this time that this game took on a Fluid Truck theme, when I settled on making the player avatar a cargo van. I had work on the mind, but I also thought the idea was fun and unique. I mean, how many games feature a cargo van as the main character?
Because the player avatar has several different states for forward motion (crashing, jumping, and so on) all the different states could be organized into a sprite sheet (pictured) which I could simply import into Unity, label, and reference within the Unity engine as I needed them.
In the asset design phase, the most lengthy struggle was choosing what would represent bonus points for a cargo van. What does a cargo van want?
A deep, philosophical question to be sure.
Even though Fluid Truck’s EV fleet is growing rapidly, I opted to go with the classic fuel canister icon (which I lifted from the web).
After a couple of days, the sprites were ready to go and the next step of the operation, scenebuilding, was set to begin.
Unity has a concept called Scenes which effectively act as little games inside the project. Each Scene can alter the gamestate by displaying different content on the screen. There’s no persistent behavior between one Scene and another unless you set up a script to handle rules between Scenes.
To elaborate further: one could create a scene called MainMenu which houses, but does not control, things like buttons, text, and a background. These are called GameObjects which may inherit some rules from the parent Scene like size, reactivity, etc.
Interactions with GameObjects are controlled by their Components which vary based on the type of GameObject. A Button, for example, may be marked as interactable, allowing a player to press it and trigger another action in the game scripts. The level of modularity is fairly intense; scenarios can be designed for any possible player interaction.
There’s an art to scenebuilding. Laying out the architecture of the game, like drafting a house, is a process that requires some forethought to avoid headaches down the road. One of the big problems I faced early on in the design was how to manage the Scene for submenus.
My first pass at the object relied on multiple Scenes and GameObjects (pictured) with some small scripts to programmatically hide buttons and text that weren’t active. This approach was fine for a game of this size but it could very quickly become complicated if the project needed more menuing features, or added additional game content that needed activation via the main menu.
The final design was far more elegant: a class, or template, called MenuOption that acted as a builder for the menu. My class defined what a menu GameObject could look like, and set up rules for behaviors at a high level. Then, when I needed to generate a new menu GameObject, instead of creating a new GameObject for the screen, buttons, and text, I could pass all of that information through the constructor which then added it to the Scene. This is much more in-line with one of the core programming concepts of DRY; Don’t Repeat Yourself.
With the menu built, the only part left of the project was the actual game. With all of the assets ready to go, this part was pretty straightforward. For the game to work, there are three basic concepts:
- The game needs to start
- The game needs to change based on things happening
- The game needs to end
Starrt(), Update(), and LoseScreen() were my answers to this reality. These were actions, or “methods,” that enabled, disabled, or changed parts of the game. A method requires something to trigger it in the game state and then performs an action or series of actions.The Start() method was triggered by pressing Play and did the following:
- Set player in motion
- Set score to 0
- Started music
LoseScreen() was triggered by a player collision with the floor or an obstacle and did the following:
- Stops score from incrementing
- Displays lose screen
- Plays fail music
Update() is a method that Unity pre-defines. It is triggered every frame and performs a series of checks that the developer can define. A few I built were:
- If player points exceed a certain amount, update the background
- If player points are divisible by a certain number, play an animation
It was around this time I got the idea to add our Head of Data and resident tiger team aficionado Micheal Nguyen into the game. Someone had sent me a picture (below) of Tiger King Mike and a quick trip to Photoshop and 6 lines of new code turned our BigQuery buff into a pouncing panther.
The most fun part of game development for me was easily bug fixes.
Playtesting and finding new bugs or exploits was menial at times, but pretty joyous when the procedurally-generated platforms began multiplying.
Or when the physics engine sent the cargo van into a cyclonic ascent above the skybox.
No doubt, there are still plenty of bugs to find and fix, but I’m happy with how version 1 turned out.
With the takeaways from Fluid Runner, I can definitely say my competency as a developer has improved. And even though Fluid Runner has the distinction of being the first Fluid Truck-themed game, I hope it’s not the last!