Hi everyone! I’m Marc, Engineering Director and Co-Founder of Altitude Games. I’m here to talk about how we write code for our games.
Core principle: Make tools and systems that empower the team
A common mistake of new game dev teams is to have their programmers import assets, make the UI, line up the sprites, make each and every level work, change the stats, etc. This is in addition to actual programming work of solving hard technical problems. This is not a good use of a programmer’s time.
Here in Altitude, a Unity programmer’s primary job is to make tools and systems for a game. This is so that an artist or a designer will have the power to make and test things on their own without help from a programmer. The result of working this way is that your team can create things with the system, which are beyond the imagination of the person who made the system in the first place.
In other words: “Make tools and systems so artists and designers do all the work.” 🙂
This is something I tell to all the new Unity programmers we hire. It is a smarter and more effective way.
Example: UI management
Let me give a concrete example of this idea and the system behind it. In our first game we made a few mistakes, code-wise: one of which was on our UI management system. Problems in this system were:
- We had a giant scene full of NGUI UI
- It needed a programmer to come in and write code to open a ui screen when a button is clicked.
- It was using a lot of memory at runtime.
- Two people who want to edit two different screens can’t do changes at the same time, because this will cause conflicts in version control.
- As you see, these were problems that can slow down production. I resolved to fix these on the next project. It’s ok to make mistakes as long as you learn from them, so learn we did.
For our new game, the goals for the new UI management system are:
- Use new Unity UI – because we like it better than NGUI
- Let a designer connect UI’s together without programmer help
- UI screens don’t belong to any scene; each UI is a prefab
- Load only the UI’s that will be used at runtime to save memory
So far, the new UI management system has met all these goals. Our designer Luna was able to make 40+ UI screens, all interconnected to one another (i.e. click one button, shows another ui). She was able to do this while I was working on another major part of the code. Yay productivity! At this point, the UI flow is laid out but no real functionality yet. After this, the programmer then goes in to add code to make the code functional (i.e. buttons will show actual contents of inventory, in-app purchase, etc). Artists will come in and make pretty art for each of the screens.
I’ll give you a sneak peek of how this works but I won’t give all the code. Instead here’s an overview of the major classes and the functions that drive the system. Each class is described in the comments.
A single UI screen is saved as a prefab in its own directory. It has these parts:
- a Canvas and other things that come with the Canvas
- Animator is for the transitions
- UIHelper script. It also has a custom button to add the prefab to the UIList
- UISettings. This is where the programmer will add code specific to this UI
To make a button do something:
- Select the button
- Drag the top level game object (i.e. UISettings) to the reference box for OnClick()
- Pick any of the functions listed. UIHelper comes with Open and Close functions as showed in the code earlier.
This is the UIList;, it’s a ScriptableObject which holds references to all the available UI prefabs.
I know there may be assets like this on the Asset Store, but I wanted a long-term solution for our teams and something that fits with our coding practices. Only a custom solution would work in this case. This is also just one of the many ways to do UI management, so build what works best for you.
This UI management system is just one of the systems we use in production. We also make use of editor scripting to make custom tools specific to the games we make. Making custom editors will make editing data more user friendly. We have several ScriptableObjects, just like UIListConfig above, to specify different kinds of data that don’t belong to any scene. ScriptableObjects are nice because you keep the data in their own separate files. So chances of conflicts on version control is greatly minimized.
Going back to my initial point: have programmers make tools/systems to empower your creative team. You’ll be surprised at what artists/designers can make if they have easy-to-use tools that allow them to iterate and improve their work quickly. This is a glimpse of how Unity programmers in Altitude work.
If this sounds like something you’d love to do, we’re always looking for great Unity developers! Check out our jobs page to see the requirements. I hope you’ve gained some insights from this article. Thanks for reading!
About the Author:
Marc Polican is one of Altitude’s co-founders and also its Engineering Director.
He has held senior or lead programmer positions since 2005 and has released over 10 games on mobile, handheld, PC, and Mac.