Like it or not, it's a fundamental part of being a developer.
Over the past year, I've learned to like debugging, and even refactoring, my code. There's a certain sense of satisfaction that comes with cleaning up code and making it neat and tidy. Perhaps you've felt it too.
In this article, I'm going to walk you through the steps I take to debug my C# code as a Unity developer. Even if you don't work with Unity, hopefully this article will inspire you to reflect on your own debugging process and better appreciate all of the hard work you do to make your code shine. 🌟
When to debug?
Before I get started, I wanted to talk a little bit about when to debug in Unity. Generally, I don't think you need to fix a bug the second you find it, unless it's game-breaking. With newer versions of Unity, I've been having trouble testing my game in the editor without fixing error warnings first. This is a bit of a pain because it means I have to stop what I'm doing and immediately address each and every bug, even if it is minor and unrelated to the main game mechanics. But in the long run, I kind of appreciate being forced to do this since it means less trouble for my code down the line.
The Console is where debug messages appear in Unity. You can find the Console at the bottom of the Unity editor window.
Debugging in Unity: My Five Step Process
Now let's jump into the meat of this article and look at the five main steps I take each time I try to fix a bug in a Unity project.
Step One: Back up my project
I use Sourcetree to back up my work and my process looks like this:
Open up Sourcetree.
Stage any unstaged files in the project I'm backing up.
Write a blurb in the Commit text box to summarize the changes I've made. Sometimes I will just note that this is a backup commit of the project before I add a new feature or attempt some heavy debugging.
Hit Push to back my project up to a remote repository on GitHub.
An image of the comment box for a commit in Sourcetree.
Step Two: Check for error codes or warnings in the Console
Next, I turn my attention to the Console and read any error messages or warnings that have popped up. Double-clicking these messages will open the script (if applicable) where the error occurs, and I can usually go from there.
Once you've worked in Unity for a while, you'll become familiar with certain types of errors.
Here are some examples you might see:
- Missing syntax like a semi-colon in a script (this is uncommon since you can't actually play your game with a syntax error like this; therefore, you'll usually catch this error in Visual Studio, well before it appears in the Console)
- Forgetting to add a scene to the Build Index in Build Settings
- Going outside the bounds of an array or list
- Missing a reference to a game object in either a script or the Inspector
- The dreaded Stack Overflow error (usually caused by a method referencing itself and thus creating an infinite loop!)
An image of a common error message in the Console. In this example, I have forgotten to add a scene to the project's Build Index.
Step Three: Check for problems in the Inspector
Often the Console will suggest that the problem is caused by an incorrect or missing setting in the Inspector. So the next thing I'll do is look at the Inspector and check whether anything is amiss there.
Here are some of the things to be on the lookout for in the Inspector:
- An empty serialized field
- A missing reference to a prefab or game object
- A missing component such as Rigidbody or Collider
- A missing script on a game object
- Using the wrong version of a Collider or Rigidbody (ie. 2D instead of 3D)
- Forgetting to hook up the OnClick() event for a button
- Using a wrong or misspelled tag/layer on a game object
An image of a common error message in the Console. In this example, I have forgotten to drag and drop a game object into a Serialized field in the Inspector.
Step Four: Check for problems in the scripts
Next, I'll open up my scripts and see if I can problem solve there.
Here are some common issues that you may run into:
- Trying to access a private method or variable from another class
- Forgetting to serialize a variable
- Using an incorrect or missing namespace
- Missing a reference to a game object
- Missing a reference to a component. This happens sometimes with GetComponent<>. You may be trying to access a component which does not currently exist on the game object. To solve this, add the component via the Inspector
Step Five: Start writing Debug.Log or print() statements
Once I've gone through the steps above and made sure that the problem isn't with something I've forgotten to do in the Inspector, then I'll start using Debug.Log or print() in my scripts. Usually by this time I have a pretty good idea of where the problem exists. I like to write my Debug.Log or print() statements with a string statement at the beginning so that I don't lose track of what I'm testing for.
So for example, if I was testing to see whether a variable was returning True or False, I'd write:
And the output would look like this in the Console:
I use this method to follow the line of logic through my scripts until I have located and fixed the problem. One last piece of advice: once you are done with a debug statement, make sure you either delete it or comment it out in your scripts. Otherwise your Console will become very cluttered with messages!
Now it's your turn: how do you tackle debugging in your projects? I'd love to hear any tips or tricks you have in the comments below.