Start using Profiler!

Do you know can check how long it takes to execute your code? You can do it by using Unity’s Profiler!

Not many people know about it, so you will obtain a new superpower for your team. ?‍♂️

Ready to learn this secret weapon? ?

Where Performance is important! ?

Making the fastest game possible is not a primary goal for most games. I get it. But It would be great to make them run in at least 60 fps.

Optimization – aint no body got time for this.

So what can you do when running out of time and ideas that you can help improve your frame rate?

There are many things, but let’s start with something that will help you diagnose the problem – Profiler! ?‍⚕️

This will also be a great opportunity to talk about last week’s post about people overusing the GetComponent() method. ?

Finding the Profiler ?

Profiler is build-in tool for Unity Editor. To find it you have to go to Window > Analytics > Profiler.

Where you can open Profiler window.

When you click on it, you should see the Profiler window!

Now, you can start your game and see what is going on in each frame!

Profiling your code.

What can you profile? ?

I’m mostly writing here about profiling your code, but Profiler can give you much more.

Available modules.

We can start with checking what’s happening with the CPU, so code execution. Later we can move into GPU/Rendering, so how things are rendered in the game. And later, go to Memory to check if the user won’t run out of memory playing our game. ?

Of course, there are more options, but I need to leave you something to explore yourself. ?

Profile your code ?‍?

Okay, let’s get to the meat. How can I profile my code?

Great you asked!

You need to learn 2 methods! Profiler.BeginSample() and Profiler.EndSample().

The first one starts a new sample – whatever happens in the code from this point, it will be counted to the sample execution time and allocation.

The second one ends the sample – which saves info how long the sample took and how much memory was allocated.

Inside the code, this can look like this:

using UnityEngine;
using UnityEngine.Profiling; // Using you need to include

/// <summary>
/// Example of how to use Profiler.
/// </summary>
public class ProfilerSampleExample : MonoBehaviour
{
    // Called on the begging.
    void Start()
    {
        // Starts taking sample 
        Profiler.BeginSample("Doing awesome things");

        // Your code goes here
        DoAwesomeThings();

        // End the sample
        Profiler.EndSample();
    }

    // Sample method.
    void DoAwesomeThings()
    {
        Debug.Log("You're awesome!");
    }
}

Samples inside other samples! ?

Yes! You can take samples inside other samples!

There is just one thing you have to be aware of. You have to keep track of which sample ends where.

We can take a quick look into the GetComponent() method and its performance using the Transform component, which every game object has.

This is the code I’m going to run.

using UnityEngine;
using UnityEngine.Profiling; // Using you need to include

/// <summary>
/// Testing performance of GetComponent and references
/// </summary>
public class Playground : MonoBehaviour
{
    // How many loops code should perform.
    public int loops = 1000;

    // Cached reference to the Transform component
    private Transform _transform;

    // Assign references
    void Awake()
    {
        _transform = transform;
    }

    // Called each frame
    void Update()
    {
        // Profile GetComponent on Transform
        Profiler.BeginSample($"Call GetComponent<Transform> {loops} times", this);
        for (int i = 0; i < loops; i++)
        {
            Profiler.BeginSample($"GetComponent<Transform>", this);
            var _ = GetComponent<Transform>();
            Profiler.EndSample();
        }
        Profiler.EndSample();

        // Profile transform property
        Profiler.BeginSample($"Assign transform {loops} times", this);
        for (int i = 0; i < loops; i++)
        {
            Profiler.BeginSample($"Assign transform", this);
            var _ = transform;
            Profiler.EndSample();
        }
        Profiler.EndSample();

        // Profile cached transform property
        Profiler.BeginSample($"Assign _transform {loops} times", this);
        for (int i = 0; i < loops; i++)
        {
            Profiler.BeginSample($"Assign _transform", this);
            var _ = _transform;
            Profiler.EndSample();
        }
        Profiler.EndSample();
    }
}

So I’m going to run 1000 times assigning results from GetComponent(), transform, and cached transform property.

Can you guess the result?

Result of running each method 1000 times.

Now we can clearly see it. It’s better to cache the references.

Let’s go bigger! ?

What would happen with 100k calls?

Result of running each method 100k times.

Enjoy your new superpower ?

That wasn’t that hard after all.

As you can see, using Profiler is not that hard after all. ?

And if you are as big of a nerd as me, you will have really good fun playing with it.

Let me know what you think about profiling and if you already used it or not. You can leave it in the comment section below.

Don’t hesitate to share it with your friend or your team. This may help optimize your game. ?

And if you want to be notified about future content on my blog, you can sign up for my newsletter!

Thanks for reading, and see you next time! ?

5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x