MonoBehavior calls optimization

What if I told you that Unity can be wasting a lot of CPU performance just by calling your MonoBehaviour functions? It doesn’t really matter what your scripts are doing. If you have hundreds or thousands of them, you should be aware that there’s a new field of optimization.

Magic methods

MonoBehaviour functions calls are slow. And I’m talking about functions like Update(), LateUpdate(), OnRender() etc. They are so-called magic methods, and if you’re familiar with object-oriented programming languages, this concept looks like calling a method using reflection mechanism (reflection enables method calls even if you don’t know the interface). Reflection calls are expensive, so Unity does everything that is possible to cache any operations, so the set of CPU instructions needed to call a magic method each frame could be minimal. But it can still be slow, very slow…

Why is it so slow?

I’m not gonna talk about the details (but if you really want to read about the details, look at the end of this article for the links), so just imagine that Unity tries to be as flexible and easy to use as possible. Making something easily costs CPU power because the engine cannot make any assumptions about your game and it needs to do a bunch of checks to call your magic functions on the right objects, in the right order, and to not crash in the meantime.

Can it become faster?

Oh this is my favorite part. Yes! It can! How? You have to take the responsibility of calling Update() function by defining your own function and calling it from a manager. This way, you’re taking responsibility for updating your objects. How much faster it can become? Well, it depends on the platform. Let me use the measurements done by Valentin Simonov on official Unity blog:

Mono with fast but no exception settings.

Here you see that the difference can be worth the time. This is a measurement of calling Update() 10000 times.

Writing a manager

I will present a fairy simple example of a manager called BoxManager that is managing BoxManaged scripts. Manager has two responsibilities:

  1. Keeping the list of managed objects updated
  2. Calling update-like functions on managed objects when manager Update() is called.

The code may look like this:

As you can see, it’s really simple. Before implementing Update() function let’s take a look at BoxManaged.cs.

It registers itself when enabled and de-registers when disabled. Fair enough. ManagedUpdate() function is a function that will replace Update() magic function. Let’s implement BoxManager.Update(), so it will be able to call all BoxManaged.ManagedUpdate() at once.

And that’s it! Really! Now in ManagedUpdate() you can do everything you would normally do in the Update() function.

Please note that I did not use foreach for iterations. Firstly, because it’s generating small amount garbage Unity’s version of Mono. Secondly, because it simply seems to be slower.

Should I care?

It depends on what kind of game are you creating and what is the target platform. Ask yourself a question – do you have many MonoBehaviour objects with Update() calls? It doesn’t necessarily need to be Update(), it can be anything that it is invoked with each frame. Then, if you’re targeting mobiles, it’s definitely worth to try! Targeting standalones? It’s still something you may consider, especially if you’re planing to have huge amount of objects.

Sometimes you may need a manager even if you’re have a relatively small amount of objects. On iOS there was (I don’t know if it has been fixed or not) a problem with OnRender() function. Having it on 30-40 objects could decrease the game’s performance twice! The solution? A manager like the one presented above, but instead of calling Update() it should be calling OnRender() code. Yes, it will work!

Please keep in mind that this is one of many optimization strategies that you can use. Yet this one is quite hidden – unless you know about it, you will have a hard time to find about this one. That’s the reason why this article has been brought to life.

References:

https://blogs.unity3d.com/2015/12/23/1k-update-calls/

 

How to Use Unity’s Resources Folder

Unity has several kinds of special folders. One of them is the Resources folder. Simple concept of storing assets is well-explained in the official documentation:

Generally, you create instances of assets in a scene to use them in gameplay but Unity also lets you load assets on demand from a script. You do this by placing the assets in a folder called Resources or a sub-folder (you can actually have any number of Resources folders and place them anywhere in the project). These assets can then be loaded using the Resources.Load function.

Still the reason why we might want to use the Resources folder may be a little confusing. First you have to understand how Unity build process is works and how Unity is able to access game assets.

Unity build process

Before you will build your game, you have to declare what scenes your game consists of. All of this can be done in Build Settings window.

build settings window

There are at least two reasons why Unity asks you to do this:

  • It needs to know what scene should be loaded first (the top scene)
  • It needs to know what assets should be included in your build (dependencies)

What are scene dependencies? They’re assets which are connected to the scene hierarchy in any way, usually as a component field.

Unity Logo object contains Sprite Renderer object that references Unity Logo asset.

Unity Logo object contains Sprite Renderer object that references Unity Logo asset.

The dependency diagram may look like this:

dependency diagram 1

In this case there are two scenes. Scene 1 is using Asset 1 and Asset 2. Scene 2 is using Asset 2 and Asset 3. What happens if you decide not to build Scene 2?

dependency diagram 2

Only Asset 1 and Asset 2 will be included in the build since Asset 3 is referenced only by Scene 2, that is no longer included in the build. Thanks to this dependency tracking Unity will include in your build only these assets, which are actually used. Needless to say that you don’t have to worry about storing assets you’re not using at the moment. It will not affect your build size in any way.

Override!

There’s a way to get around this process. If you put your assets into a Resources folder, they will be always included in your build. But be careful! You need a really good reason to do so!

As I said before, in most cases when you need to use an asset, you make a reference to it within a scene. It’s really easy to use any kind of attached asset this way. So why would you need to use an asset without keeping a reference to it? There may be several reasons and each one depends on specific needs of the, but let’s look at one case what is quite common for most games.

When an asset is directly referenced from the scene, it will be loaded into the memory before your scene will be launched. Thankfully to that, player will not experience any frame-drops related to assets loading (with small exceptions). The price is of course the time needed for these assets to be loaded. Sometimes it may be not acceptable.

Example – loading screen with different backgrounds

Many game loading screens are displaying random images to be less boring.

Many game loading screens are displaying random images to be less boring.

Loading screen is something that usually is also a scene. Let’s think of a case when you want to display a random image on the background while your actual game level is loading. You’ve collected 15 images and you add these to loading scene images rotation script. It is working great, but when you play your game you realize that your loading scene requires more time to load than you need to pass your actual game levels!

This is caused by assets pre-loading mechanism and can be easily fixed using Resources folder. First remove all the references to your textures from the scene. Then put your images into Resources/LoadingImages directory like this:

resources images

Then somewhere in the code you can use a code like this one:

Note that Random.Range() returns a random number between first argument inclusive and second argument exclusive, that’s why there’s +1.

If you will need to attach this texture to an Image component, you can do it like this:

A word of caution

Use Resources folder only when you really need to. Loading assets on demand will make your FPS rate drop, and having indirect dependencies is makes your work much more difficult.  It’s worth to mention again that these assets will always be included in your build, even if you don’t use them. You have been warned!

A Story of NullReferenceException [Part 1]

Once upon a time there was a little boy living with his mother alone between the mountains. They lived a peaceful life. One day the boy’s mother got very sick. The boy called for a doctor, the best in the valley. When the doctor finally came, he examined the woman. Unfortunately, there was only one medicine for her illness and this medicine was very hard to get. The only known location was far away from there, on very dangerous lands, full of traps and monsters. Without thinking too much, the boy took his wooden sword, backpack and he went on a trip where… NullReferenceException.

NullReferenceException

If there’s one thing that is common for most of Unity games, this thing is NullReferenceException. This little fella can be quite a nuisance, especially on mobile platform, where you most probably want to have a script call optimization set to Fast But No Exceptions. That’s because any exception will cause your application crash immediately. Is this worth the risk? It depends on the time your game requires to execute all the scripts in each frame.  The more time it needs, the more you will benefit from enabling the optimization.

What NullReferenceException is?

Before killing the dragon, we must fight the dragon. Before fighting the dragon, I would say that we have to get to know the dragon. NullReferenceException is so common issue, that is has its own Unity documentation page! But let’s compare it with official .NET documentation definition.

Official:

In this article we will talk about techniques that will help you minimize NullReferenceException occurrence possibility.

Unity:

A NullReferenceException happens when you try to access a reference variable that isn’t referencing any object. If a reference variable isn’t referencing an object, then it’ll be treated as null.

So this means that if you have a reference (field or variable) that is not pointing to any object (is null) and you try to access it (access parameter, field, or execute a method of this non-existing object), then you will receive a NullReferenceException.

But… there’s one subtle, yet important, difference with NullReferenceException when working with Unity objects. Normally, you may do a check if an object is null before trying to do anything with it:

But Unity objects are a bit different. Unity objects can report themselves as null even if they are still referencing an object!

No, that’s not a bug! Some referenced objects are scene objects. Imagine what happens if a scene is being replaced by another scene – all regular scene objects have to be destroyed. Since Unity cannot update your valid references inside your code (they still will be valid after destroying the scene), it is faking a null check for those that you are still referring to, so it will (should) stop you from use these any longer. In case you do try to use any of these objects, you may receive a message like this one:

reference object destroyed

It is also an exception that will crash your app, so be warned!

Fail Fast

The worst and yet the most common case of NullReferenceException is when your component expects some other objects to be passed into it through the inspector, but for some reason somebody didn’t do it.

The example above is a simplified situation when you want to display a label when player touches the star. Collider other is guaranteed to be a valid reference (based on documentation), but what we cannot be sure about, is the scoreText field that should be visible in the inspector. What if somebody forgets to assign it? You will know about it only after trying to touch the star. That’s definitely too late!

We can handle these kind of situation using Asserts (we talked about asserts before). Asserts will tell us if something is wrong, and it’s a wise choice if all the checks can be done right after the scene is launched. Let’s try to add an assert like this:

This code will yield an error right after the scene is started. We no longer have to wait for the player to touch the star. That way we can check if everything is OK with the scene just by launching it!

Do I have to add an assert for each inspector object? Yes! You cannot trust that someone  doesn’t break your scene references.

Public field is not bulletproof

Have you noticed that public fields can be accessed from any place? Yep, this can be bad. This means that any other script may get to it and set it to whatever it wants to. Assert won’t help us if other script will decide to replace our reference in the middle of playing the game.

To make it a little more bulletproof, we can make it private. Private fields can be displayed and assigned within the inspector, but a field like that needs a [SerializeField] annotation:

Now, the field cannot be accessed outside the current object what makes the risk of unexpected NullReferenceException significantly lower.

To be continued…

You can read the second part of this article here.

Mobile Optimization – Garbage Collector

What is the Garbage Collector? Let’s look at a definition on MSDN:

The .NET Framework’s garbage collector manages the allocation and release of memory for your application. Each time you create a new object, the common language runtime allocates memory for the object from the managed heap. As long as address space is available in the managed heap, the runtime continues to allocate space for new objects. However, memory is not infinite. Eventually the garbage collector must perform a collection in order to free some memory. […]

If C# or JavaScript is your first (and only) programming language then most probably you are not aware of how difficult is to manage application memory. In languages like C/C++ you have to decide when memory is allocated and when it is freed. Make one mistake, and you will either have a memory leak or your application will crash in an instant.

Of course if something is difficult to manage then it requires time to think about it. Now, we live in the world where we want to release our products to the market as soon as possible, so we’re trying to find a way to make everything as simple as possible. One of these things is allowing garbage collector to take care of freeing the memory.

Sounds great, doesn’t it? Yeah, garbage collection is a real life saver, but it has a downside too. Garbage collector runs from time to time and it requires your application to freeze for the time being (There’s a garbage collector mode that allows to run without freezing the app, but you’re not allowed to tune the Unity garbage collector settings.) and you have little control when the garbage collection should be launched. This is not an issue for a business application where the interface usually static, but may be an issue for a game where even a short pause can cause the player to loose the game. And what players hate the most is losing when it’s not their fault…

Garbage collector and games

Last time we talked a little about Unity profiler and garbage collection.  The rule is simple – we don’t want the garbage collector to start its job. To do so, we have to stop generating garbage. Of course it’s impossible not to generate garbage at all, but we can significantly reduce amount of generated garbage, so garbage collector will run once per ten minutes instead of once per ten seconds.

Using Pools

One of techniques to minimize the garbage is to reuse existing objects instead of creating new. This technique is called object pooling and we talked about it last time. In most cases you will benefit the most by using this technique, so this should be the first thing you should take care of.

There’s a great free library that you can use to build your own pools. It’s called Smooth.Foundations and it is available on the Asset Store. Unfortunately the website with its documentation is down, but the code is really simple to understand. Here’s an example pool that creates a pool of GameObjects with SpriteRenderer component.

From line 6 to 10 we create a delegate that defines how pool object should be created. From line 11 to 15 there’s code responsible for resetting the object to its original state (after releasing it).

Then the pool can be used this way:

Using Arrays

You may use arrays, but remember not to allocate these during the runtime. If any function needs to return an array of values, use an existing array and pass it as an argument.

Usual approach

GC-friendly approach

As you may have noticed, using gc-friendly code requires some more effort. First, you have to know the upper limit (in this case 32). You have to be sure that this limit is not exceeded, because your game will crash. Then if you want to iterate through these items, you have to use the size value instead of the size of an array.

Note that I used the ref keyword here. Ref means that this value should be passed by reference but since arrays are always passed by reference, it is not required in this case. The only reason it was used, was to increase the readability of GetNumbers() method call. If you see a ref then you know that something will get out that function using the passed parameter.

Using Lists

Using arrays directly may be not the best choice. Instead, you can use a List. The List in fact is an Array wrapped by a quite useful handling code, that guarantees you safety and you don’t need to worry about array sizes to much (and some other things too).

Yet you have to be careful. If you exceed the List array size, it will allocate a new bigger array. Since we want to minimize the number of allocations, always create lists using constructor that takes the capacity:

What about iterating through a list? You may know that or not, but Mono compiler that comes with Unity (Current Unity version at the time of writing this article is 5.2.3) has a bug that allocates memory when using foreach loop on collections. It’s not much because it is “only” 24 bytes, but executed many times will quickly exhaust your memory and trigger garbage collection. Instead, use for loop whenever possible.

Here’s an example code. Note that this time we don’t need a size variable.

Consolidating strings

There are some things that you simply cannot get around. One of those things is consolidating strings. When done, it will always allocate a new string. You can optimize this process a little by using StringBuilder instead of the add (+) operator.

The add (+) operator approach:

The StringBuilder approach:

Have you noticed that I used a using instruction to get a Disposable object from the pool? This is another method to use the pools. It’s much safer, because you won’t forget to take the borrowed object back.

Is that everything?

Of course it isn’t! One note though. Please, keep in mind that running your code in Unity editor will generate more garbage than running it on the target device. You may find yourself in a situation when you try to optimize the garbage when it is not generated at all on the target device. This is because the Unity does some nice optimizations when your game is build, and you always should run the profiler on already built game to know what should be optimized and what not.

Wrong Import Settings are Killing Your Unity Game [Part 2]

There are many things that may go wrong with your game development. Your models may have too many triangles for your target platform to handle, your algorithms may be too expensive for your CPU, and also you may be using too many materials so batching won’t work efficiently. These are difficult issues, and you as a game developer should always remember to keep good balance between visuals and performance. Yet, there are some things so simple that we often forget about their existence, but these can have a serious impact on your game performance.

Last time, in Part 1, we talked about how texture import settings can kill your game performance. This time we will talk about sound import settings and why it matters.

Audio Clip Import Settings

When working with Unity many things can keep their default settings set and everything will be working just fine. Of course, defaults are not optimal in most cases, but your game should be working OK. This rule unfortunately does not apply to Audio Clip Import Settings.

Audio Clip (sound files) importing is working very similar to texture importing. Unity supports many different audio formats, but in the end it converts them all to preferred (by the engine) format. Currently, in Unity 5.2.1 this can be PCM, ADPCM, Vorbis/MP3 and HEVAG. Note that not each platform can handle all of these compression formats, and some platforms have only one format available (e.g. WebGL can work only with AAC audio clips).

Memory matters

All Audio Clips are imported by default with “Decompress On Load” Load Type and “Vorbis” Compression Format.

These are default import settings.

These are default import settings.

You should be very careful with this setting, because using it on all your audio clips (Unity does it by default!) may consume large amount of your game’s memory! Do you see the info box on the screenshot? Original file size is computed to 35.9 MB and the imported size to 10.7 MB. This means that this Audio Clip will increase your game (archive) size by 10 megabytes, but playing it will require nearly 36 megabytes of RAM! This does not sound too scary if you’re building a game for PC where it is quite common to have 8 gigabytes of RAM, but mobile devices are still very limited on that manner.

When I should use specific Load Type?

Let’s get this straight. Each Load Type and Compression Format combination can be used and you’re the one who knows best which one should be chosen. There are three Load Types:

  • Compressed In Memory – Audio Clip will be stored in RAM and will be uncompressed when played. Does not require additional memory for playing.
  • Streaming – Audio Clip will be stored on a device persistent memory (hard drive, flash drive etc) and streamed when played. Does not require RAM for storing and playing (at least this value is not significant).
  • Decompress On Load – Audio Clip will be stored in RAM uncompressed. This option requires the most memory but playing it won’t require so much CPU power as the rest.

So, which one to use? It depends…

Music and/or Ambient Sounds

Music is stored in long Audio Clips so it can consume a lot of memory. For sure, we don’t want music to be decompressed into the memory then played. You have two options here:

  1. Use Load Type “Streaming” and Compression Format “Vorbis”. This combination will use the least amount of memory but will require some CPU power and disk I/O throughput.
  2. Use Load Type “Compressed In Memory” and Compression Format “Vorbis”. The only difference from the first solution is that it will exchange the disk I/O with some memory requirement. Note that you can adjust the Quality slider to decrease compressed clip size in exchange of sound quality. Usually 100 percent is a way too high. I would recommend something around 70 percent.

Note that if you have more than 2 music/ambient sounds clips playing like this, it can consume a serious amount of CPU power.

Sound Effects

Sounds effects are usually short or medium Audio Clips. Also these can be played frequently or rarely. Here are some rules:

  1. For frequently played and short Audio Clips use Decompress On Load and PCM or ADPCM Compression Format. When PCM is chosen, no decompression is needed and if audio clip is short it will load very quickly. You can also use ADPCM. It requires decompression, but it is much lighter to decompress than Vorbis.
  2. For frequently played but medium Audio Clips use Compressed In Memory and ADPCM Compression Format. ADPCM is around 3.5 times smaller than raw PCM and decompression algorithm will not consume as much CPU as Vorbis.
  3. For rarely played and short Audio Clips use Compressed In Memory and ADPCM. For the same reason as described in point 2.
  4. For rarely played and medium Audio Clips use Compressed In Memory  and Vorbis Compression Format. This SFX might be too long to be stored using ADPCM and played too rarely, therefore additional CPU power required to decompress wouldn’t be a such pain.

Summary

Always remember to check your Audio Clip Import Settings. These are silent performance killers of your game. Set these right, and you will get additional CPU power for things that matters.

Also please take a look at the manual for technical information about import settings.