Player is Null: Creating Versatile Code
For over a year, I have been a Gameplay Programmer for Drillbit Studios, which was founded within Indiana University’s game design program. The project had started about a year before I joined the team, as I was working on another project at that time. The process of being integrated into a new team and project is a weird combination of eagerness, curiosity, and a little bit of suspense, especially knowing that you're going to be working with new people and their vision of what this game will become for a long period of time.
The game we developed has just been released to both mobile platforms, which is
titled THIS IS NOT A DRILL. The game has the player take control of a dwarf with a
large drill for an arm, where his goal is to climb up a mineshaft by drilling through
falling blocks as lava rises beneath him. The two main aspects that I worked on was
the objective systems, which had the player perform certain tasks for a coin reward,
and the upgrade system, which lets the player spend coins to upgrade the various
powerups in the game.
It’s needless to say that both these systems revolve around the Player object (we will
just refer to it as the Eustace for now on, since that’s the dwarf’s name in this
prodigiously lore-filled game). The objectives need to see what the Eustace has
accomplished while the upgrades are comparable to skill points. It’s also safe to
assume that these systems must always be present in the game. The problem lies in
assuming that the Eustace will always exist within the game, and making it so that
both systems will break if the Eustace doesn’t exist. Well, that’s exactly what I did.
Condensing the Game
At first it seemed that always needing a player reference was okay to do, but it doesn’t take much for stable-looking scripts to break upon the slightest of changes. In this instance, all we did was move the main menu to the same scene as the game level, which contained the scripts for upgrades and objectives. To put it simply, we wanted the game to seamlessly transition from the menu into the gameplay. So when the menu is active, you can probably guess what isn’t. Yep, that’ll be Eustace.
As soon as we moved everything, we were bombarded with errors, most of them pointing at two scripts; Objectives and upgrades, with the predominant message being “Player is null”
The Quick Fix
The best thing one can do to prevent this from happening is making things
that can be optional, optional. The next best thing is to make something
that isn’t optional throw an custom error message if the reference is null.
It’ll save a lot of time debugging. The objective system was the easy fix.
Since the logic that tracked the player’s objective progress was within the
same function, all it needed was a “if” statement checking if Eustace was
referenced. If not, then the code doesn’t run. Things weren’t as simple for
the upgrade system.
Making Systems Work, Null or Not
The upgrade system used to have to be able to communicate with the player and the Gamecontroller script simultaneously. The Gamecontroller holds the logic of saving the levels up each upgrade. When purchasing the upgrade, it would call a function in the Gamecontroller to upgrade a single level, then get the new level and send that level to the player. Essentially, most of the logic was put into the update function, which is called every tick.
I learned that this was not only going to break if the player doesn’t exist, but it’s overly complicated and resource-demanding than it needs to be, especially with almost everything being in the update function. So, I scrapped most of the code and rewrote it to be more “linear”. Now, upon upgrading, it calls to a method within the Gamecontroller, which increases the level by one, and when Eustace is enabled, his script retrieves the levels from the Gamecontroller.
In conclusion, three things can be learned from this experience. First, don’t put everything in the update function, and have methods run only when necessary. Secondly, make references optional when they can. If not, create a custom error message if the reference is null. Lastly plan out how classes, scripts, methods, etc will communicate between each other before implementation. It’s easy to get lost.
Thank you for taking the time to read this blog. I hope you enjoyed reading about one of the many experiences there are in creating a game. If you have any questions, feel free to check out my contact information.