Avoiding Update() in Unity, using profiling and making your monobehaviours more efficient.
Recently I’ve been working on many exciting things, few of which I can talk about in too much detail… But one thing I can talk about is some of my experiences using Unity and some of the lessons I have learnt. In this post I’ll be talking about the small matter of making more efficient games in Unity.
First off I just want to say I’ve fallen into the trap of writing a rather dramatic “Buzzfeed” style title. The Update() function is not Unity’s goto. It’s an incredibly useful function that you will need to use in certain cases. This post is about making you realise that it’s not to be used everywhere and will hopefully get you thinking about what your game actually needs to be doing once every frame.
Let’s get everyone on the same page, the Update function is a function in the monobehaviour class, which Unity describes as; “the base class every script derives from”. It is a function that is called once every frame, if the gameobject your script is attached to is enabled. So if you attach a script to a gameobject that looked like this;
Then place that game object on an empty scene and hit play your console will be spewing out Hello World once every frame.
Obviously you can have multiple game objects on your scene all with scripts attached to them, and every one of those object’s Update functions will get called every frame. This means if you have 100 objects on a scene each with their own Update function, you will be calling 100 Update functions every frame.
I’m sure you’re now starting to see how things can get messy.
So the problem that arises is how can we keep all of our update calls in check. When making games most teams use an agile approach, you build something small and functional and you iterate on it, improving and adding more content and functionality. In Unity terms this often means in your first few iterations your game is small, but grows gradually; adding more game objects to your scenes and adding more functionality to your scripts. This means your problems with efficiency can creep up on you. Scripts with huge functions being called once a frame where fine in a scene with 10 objects, but now you’re running that script on a 100 game objects in a scene with hundreds more objects, it’s not the same story.
Finally we get to the point of this post; don’t be lazy, you’ll hate yourself later, let’s look at a recent example of when I was lazy.
In the game I’m working I have some button that allows you to consume an item. This button needs to display how many items the player has and show when a user has consumed or gained an item, which can happen in game.
Originally I attached a script that had an update function that looked a bit like this;
This seems perfectly logical, but it is unnecessary. I know when I need to update my item counter, it’s not once a frame, it’s when the number of items the player has has changed. So there is no need to call a function that updates your game object every second, even if it’s just hitting an if statement and moving on, it’s still an unnecessary computation. For this particular example I implemented a solution that made use of an event system, where my UpdateItemCounter() function is only called when an event telling me that the item counter has been changed was dispatched.
This is one example of a simple problem with a simple solution but the basic idea can be expanded and applied in most Unity games I’ve seen, and there are many ways that you can work around performing unnecessary work every frame. This could include an event system like I used or even something simple like making use of coroutines and controlling how frequently you are looping on certain pieces of code.
One of the best ways to start making your Unity game more efficient is to use Unity’s profiling tool. This is a tool that lets you see how much time is spent on different parts of your game. You can play your game with the profiler turned on and see how much time your game spends on different processes. This is where we caught my laziness in the above example, and profiling is a great tool in general to help you optimize your games, and more relevantly to this post; Help you catch unnecessary use of the update function!
Basically this post is meant to highlight 2 things I’ve learnt over the last few weeks;
- Having access to a function that can be called once a frame is a huge temptation. It gives you the capacity to do things in a crap way, and you should make sure that you always try and do things in a clever and as efficient way as possible.
- Use profiling to catch your mistakes. When working on big projects you are bound to miss out either on your own inefficient code or someone else’s. Profiling is a good quick tool that can catch unnecessary computations or lazy implementations, and help you think about how you could be doing things better.
I hope you found this helpful, let me know if you have any questions or suggestions!