Optimizing Mobile Apps in Unity

You can access the full course here: Mobile Game Development for Beginners

Caching Objects

In Unity, there’s many functions we can use to easily get objects/components.

  • GameObject.Find
  • GameObject.GetComponent
  • GameObject.FindObjectOfType
  • GameObject.FindObjectWithTag
  • Camera.main

Calling these every frame or frequently is not recommended. What you should do, is cache the object so that you can easily use it whenever you want.

Here’s an example where we find the “Ball” object every frame and change its color to blue. This is very un-optimized.

void Update ()
{
    GameObject.Find("Ball").GetComponent<MeshRenderer>().material.color = Color.blue;
}

A way to optimize this, is to cache the property. We create a mesh renderer variable and in the Awake function, set this to the ball’s mesh renderer. Then in the Update function, we change the color every frame.

private MeshRenderer ballMeshRenderer;

void Awake ()
{
    // get the ball's mesh renderer
    ballMeshRenderer = GameObject.Find("Ball").GetComponent<MeshRenderer>();
}

void Update ()
{
    ballMeshRenderer.material.color = Color.blue;
}

Reducing Function Calls

If you have an expensive function that isn’t necessary to call every frame – don’t. Stuff like AI updates, pathing, etc… we can call it every 0.2 seconds rather than every frame. They will basically feel the same, yet with major performance increases.

Here’s an example where we’re calling an expensive function every frame. At 60 FPS, this means we’re calling the function 60 times a second.

void Update ()
{
    ExpensiveFunction();
}

void ExpensiveFunction ()
{

}

An alternative, would be to call that function every 0.2 seconds. This bring it down from 60 times a second to 5 times a second.

private float lastCallTime;

void Update ()
{
    // call the function every 0.2 seconds
    if(Time.time - lastCallTime >= 0.2f)
        ExpensiveFunction();
}

void ExpensiveFunction ()
{

}

Other Optimizations

  • Reduce Debug.Log calls.
  • Reduce frequency of Raycasts.
  • Don’t use Loops in the Update function.
  • If you’re instantiating lots of the same object: use Object Pooling.

Transcript

Hey, everyone. In this lesson, we are gonna go over a couple different scripting optimizations that you can implement in your projects in order to increase performance. As with mobile games, especially, performance is something you always need to keep in mind.

So, the first thing we’re gonna look at is caching objects. Now, whenever you wanna access and object inside of Unity, you might think that, oh, the GameObject.Find function, I can just easily find objects that way or get a component. Here in this example, I’m finding the object, Ball, and accessing the MeshRenderer component to change the color to blue every single frame. Now, this is a very expensive line of code and when I say expensive, I mean that it is using a lot of processing power and it takes quite a long time to run in terms of a function.

And what we can do with this is actually cache of the MeshRenderer component of the ball instead of having to find the ball every frame and find the MeshRenderer component every frame. So, instead, what we can do is cache it. We can create a private variable for that Ball MeshRenderer and in the Awake function, that is where we will call the GameObject.Find function to find the ball object and get the MeshRenderer component.

What this will do is greatly reduce the amount of time it takes to run the Update function as we are only calling the GameObject.Find and GetCompnoent for the ball once in the whole game, whereas before, we were calling it probably around 60 times a second if you’re at 60fps on a mobile. This is just a lot easier and this is really what you should be doing if you do have these sort of large and expensive functions being called quite regularly.

Here is also a list of all the other sort of functions that you should really cache if you’re calling them every frame or if you’re calling them quite often. Your GameObject.Find and then you’ll see we got GameObject.FindObjectOfType. Now, this is probably one of the most expensive ones as what this is doing is, like GameObject.Find, GameObject.Find is looking through the scene for a specific object with a specific name.

Well, what GameObject.FindObjectOfType is doing – is doing the exact same thing as Find but for each of those objects, it is actually pretty much calling the GetComponent function so it’s looking through every object and every component for a specific one and that is actually quite a performance hitting function that you should only really be calling once for an object when it’s been initialized.

Then, there is FindObjectWithTag which looks through all the objects for a specific tag. This is actually what the camera does, the Camera.main. Whenever you call Camera.main, this is, behind the scenes, what it is calling. So, when you think of that, it’s really something that you shouldn’t really be calling every frame as well. Same with GetComponent, and of course, Camera.main.

Something else you should also keep in mind when creating functions inside of Unity is reducing the amount of time you need to call them. Sometimes you’ll have a really expensive function like something to do with pathfinding or calculating something quite large. In this case, you don’t necessarily have to always do it every single frame. If it’s something that is not required every single frame then you can actually reduce that quite a bit.

For example, if it is a pathfinding function, you don’t need to constantly be updating the agent’s path every single frame. Instead, you can do it every point two seconds, like we see on the right. And what we’re doing is reducing the amount of times we call this function from 60 times a second, if you’re running at 60fps, right down to five times a second.

And all we’re doing is creating a private variable called lastCallTime and we are just checking to see that if our current time take away the last time we called this function is greater than or equal to point two seconds or really whatever frequency you want. Then we are calling the expensive function and of course then, in the expensive function, you then want to set the lastCallTime to equal the current Time.time, so that it is then reset and it keeps on going around to call that expensive function every point two seconds as if it is something to do with pathfinding, it is not really that noticeable a difference from every frame to five times a second.

Finally, here’s just a list of other optimizations that you really should keep in mind when creating projects in Unity and especially in mobile. Debug.Log is one that pops up quite a lot, you’ll constantly be using this to debug stuff and test various functions out but when you actually release your game, you don’t need these, as the player, at the end of day, will never see these Debug.Logs and what they are, they’re actually quite expensive, whenever you call one, there’s quite a lot that goes on behind the scenes and if you actually look at the profiler when calling Debug.Log, it’s actually pretty expensive.

Also, reducing the frequency of Raycasts. Try and avoid calling Raycasts every single frame if you have to, you could use something similar to this function call optimization where you call every point two seconds. But yeah, Raycasts and Raycast hits are pretty expensive as well. Also in Update, try and avoid using Loops, try and avoid Looping through stuff every single frame as it does have to Loop through every single element inside that array or however many times you’re calling that Loop in the Update function.

So, yeah, just try and avoid that and also if you’re instantiating a lot of objects that are the same and they’re being destroyed such as bullets or particle effects, you can actually implement Object Pooling. And what this does is, when an object is created, it’s not actually instantiating it, it’s actually taking it from a Pool which you actually instantiate a bunch of the same objects at the start of the game and you sort of reuse them so instead of destroying them at the end, you just disable them and when you want a new one, they’ll Pool a look through, see if they have one available, re-enable it or if there’s not one available, it will create a new one. This is known as Object Pooling.

There are a large amount of different ways to do it, you can go from very simple options to very complex options but Object Pooling is something you do need to keep in mind if you’re creating a game that uses bullets or lots of particle effects. So, yeah, that’s about it. I’ll see you all in the next lesson.

Interested in continuing? Check out the full Mobile Game Development for Beginners course, which is part of our Unity Game Development Mini-Degree.