Phoenix Point

View Original

Unity References Basics for Game Developers

We wanted to share some insights from our Snapshot Games development team on the making of Phoenix Point. In this behind-the-scenes developer diary, our programmer, Filip Slavov shares some Unity reference basics when it comes to coding video games.

TL;DR

  • Use object references instead of hard-coding stuff. PLEASE!

  • Project asset files are referenced via unique id stored in the metafiles.

Who is this for: game developers enthusiasts with some basic knowledge of assets project organization.

Hard-coding

Even if you’re not a programmer, you probably heard that seniors cringe at the sight of “hard-coded” stuff. What exactly does this mean? Well, here’s an example code:

var crabmanObject = GameObject.Find("Crabman");

This code finds a "Crabman" object in the scene. This doesn’t seem so bad, so why is it frowned upon? Well, Crabman is the working title of one of our characters. Later on, it became known as "Arthron". So, should we start searching for that? Maybe both names? If someone changes the name of the object in question, will they be conscious enough to change all the places in the code it is mentioned? The answer is most likely no. Especially when the concepts in question are game design-related and supposed to be created and changed by game designers.

We can take this a step further with the Unity legacy Resources system for loading assets on demand during runtime:

var prefab = Resources.Load("Characters/Alien/CrabmanPrefab");
var crabman = Instantiate(prefab);
crabman.Kill();

In this case, crabman prefab is loaded by path. If someone moves the prefab into another folder or renames the prefab file, it’s gg.

You may think this is a small nuisance, but you will be wrong! During development assets keep changing names and locations constantly as the project evolves!

Bonus: this is one of the reasons some programmers are fond of minimal to no comments in the code or any documentation. Code keeps changing and developers will surely forget to update some comments or documentation. In that case, can you trust them at all? “Trust in the code,” they say. “Write a self-documenting code,” they say. And I completely agree with them, but I don’t want to start any pitchfork mob here. :D

The solution: References

Of course (hopefully) no sane Unity developer searches game objects in the scene by name. One of the great Unity features is linking Unity objects by “Reference”. Here’s an example:

Here, instead of hard-coding names, we’re exposing a field of type TacticalActor to be set by some level designer in the Unity Editor Inspector by simple drag and drop. They can change it however they want - rename the object or move it in the scene hierarchy and the code won’t be affected. They don’t have to look at that nasty code too. It’s a win-win! The only downside: if they delete the referenced object, the reference will be lost (null), and have to remember to fill it back with another object if the code requires it. Developers usually add some validation code in OnValidate() method to prevent issues like this.

This also works with the legacy Resources system where we load assets by file path as mentioned above. Instead of hard-coding a file path to an asset, just expose some field to be filled out by a designer.

Now, this is how your Unity senior probably looks:

GUIDs & Meta files

This is a simple but very powerful concept used everywhere in Unity. It helps create an effective work environment where designers don’t need to know how to code in order to change stuff. But how does it work really? This goes down to the Unity serialization system, which is too deep to discuss here. What you need to know is that every Unity object (scene or asset) has a unique id (GUID + Local Id). When you set a reference to an object it actually stores the object’s id. This way renaming or moving the object doesn’t affect the reference. Object ids can’t be modified by the user (at least not directly) which makes it mostly safe.

Where are these object ids stored initially? For scene objects, those are stored in the scene file itself. For file assets, it’s a bit different. Keep in mind that when you put a .fbx or .png file in the project, Unity can’t modify it to add additional data. All settings or metadata Unity needs to know about some file, needs to be stored externally. Unity does this by creating a metafile next to your original file. So "Crabman.fbx" would have a "Crabman.fbx.meta" file automatically created where all settings are stored. That meta contains also the unique id of the asset! When you move/rename the file in the Unity Editor, it moves/renames the meta with it. Of course, if you move the file outside of Unity by using your file browser, you’re on your own. If the file loses its meta file it is considered as a new file and all references to it will be broken!

This is often a problem with newcomers that are used to working with file browsers or other tools and they need some supervision at first. This is also a problem for any version control system. When it does rename/move/delete operations, it also needs to do it for the metafile as well.

This article is a warm-up for an upcoming article on Unity References Meet Asset Bundles coming soon, also from Filip. Stay tuned and thanks for reading!