UnityToolbag – Library Overview

One of the greatest powers of the Unity is extensibility. You can see this especially by looking at the Asset Store. There’s plenty of scripts that will extend your Unity editor capabilities and some of them are totally free! In Overview series we will talk about this kind of assets.

UnityToolbag is a carefully prepared set of scripts that can be useful for any kind of project. These scripts were written for Unity 5 and may not work in earlier versions. We will talk about some of its capabilities. If you’re interested in any of them, please visit the project’s page.

CacheBehaviour

Unity 5 has changed MonoBehaviour’s API. Since MonoBehaviour is the most frequently used type in Unity scripting, the Unity developers decided to upgrade user scripts and libraries automatically when it is needed! As a result, if you want to access components like Collider now, you have to do it using GetComponent() method this way:

var collider = GetComponent<Collider>();

This approach has one big flaw.The GetComponent() is known to be expensive in terms of the execution time. As you might have missed to notice, calling it repeatedly in Update() methods may have serious impact on your game performance.

To get around this, the Unity documentation suggests to load the reference inside OnEnable() or Start() methods and assign it to a private field:

private Collider collider;

void OnEnable() {
    collider = GetComponent<Collider>();
}

This is much better approach because the component is retrieved only once per script, but still there is a risk. For some scripts the components might be not available right after the start. The component can be added during the run-time when it is adequate and only then it will be actually needed. What to do then?

There’s another method that is called lazy loading. It’s “lazy”, because it is done only when it is needed. It can be achieved using a C# property.

public Collider collider {
    get {
        if (_collider == null) {
            _collider = GetComponent<Collider>();
        }

        return _collider;
    }
}

private Collider _collider;

OK, that’s a lot of code for one GetComponent() call, isn’t it?

CacheBehaviour to the rescue.

In fact somebody has just written all of this for us! The class is called CacheBehaviour and it extends MonoBehaviour by implementing all standard (known from Unity < 5) properties in a very elegant lazy loading manner. To use CacheBehaviour just use it as your base type instead of MonoBehaviour.

using UnityEngine;
using UnityToolbag;

public class MyScript : CacheBehaviour {
    // ...
}

UnityConstants

As a developer you may have already known that there’s nothing worse than hard-coded literals used in many places in your code (OK, there are worse things than that). Let’s talk about Unity tags. You can tag many objects by a tag of your choice, then use this tag name to find or compare these objects. It works fine, but if you don’t use any constant to hold the tag name and put it in a single place, it might be difficult for you to track down all the places where this tag is used. You can always grep your files, but if you do that, it means that you’ve failed to maintain properly your C# code.

UnityConstants is a clever script that will generate a single UnityContant.cs file for you that contains constants for the following:

  • Tags
  • Sorting Layers
  • Layers
  • Scenes in the build configuration

You can run this tool by choosing Generate UnityConstants.cs from the Edit menu. The first time you run the tool, you will be prompted for a directory for saving UnityConstants.cs. Each time after that, it will find that file and replace it. Then it can be used that way:

var go = GameObject.FindWithTag(UnityConstants.Tags.Player);

Please make sure to check the docs to know how the file is structured.

Future and Dispatcher

Here I will describe two features at once because these are closely related to each other.

As you might know, Unity API is not thread-safe, you’re allowed to create threads without any practical limitations, unfortunately the Unity API should be called from the main thread.

Why creating threads when there are coroutines? Let me get this straight. Coroutines have nothing to do with threads. These methods can be executed piece by piece over time but still everything is done by a single main thread. If coroutine attempts to execute time-consuming operation, the whole application freezes for the time being.

Threads are different. The execution of separate threads is managed by the operating system (this actually depends on the .NET implementation) and if you have more than one logical CPU then many threads are executed on different CPUs. Thanks to that any expensive operation will not freeze your game but at most it will slow it down a little bit (yes, even if the operation is executed on a different CPU, the data bus is still shared and synchronized).

Now, if your expensive operation is done, probably you want to get with this data back to the Unity somehow. We already know that we should do this using the main thread. For this purpose, we can use a Dispatcher.

The Dispatcher is a small component that should be added to the scene when you want to use this component. It contains two static methods InvokeAsync(Action) and Invoke(Action). Call any Invoke* method from any thread and when the Dispatcher Update() method is executed by Unity itself (it is always executed by the main thread), the provided Action will be executed immediately by the Dispatcher.

private void ComputeSomethingExpensive() {
    var thread = new Thread(() => {
        // example: expensive computation of camera position
        Vector3 position = /*...*/;

        Dispatcher.Invoke(() => {
            // I'm in the main thread
            Camera.main.transform.position = position;
        });
    });
    thread.start();
}

What about the Future? Yes, I said that it is closely related. Now I’m gonna prove it!

See the example above? It’s interesting that we’re using nested callbacks. Nesting the callbacks is usually an ugly thing. If you want to provide a method that will return the computed position (the example case), then you have to create another callback.

There’s a software design pattern called the Future. The .NET provides futures if you use System.Threading.Tasks namespace, but the Unity uses an outdated version of Mono that lacks this functionality. The UnityToolbag Future provides this functionality, and it requires a Dispatcher component to be added to your scene (I will tell you why in a moment). Let’s take a look at the example showing how we can refactor the code from above:

private Future<Vector3> ComputeSomethingExpensive() {
    future = new Future<Vector3>();

    future.Process(() => {
        // example: expensive computation of camera position
        Vector3 position = /*...*/;
        return position;
    });

    return future;
}

This looks much nicer, doesn’t it? The future is using ThreadPool logic to execute the code passed to Process() function in a separate thread. Then the future object is taking the control. As you may notice, there’s no assignment to the Camera transform yet. It should be done like this:

var future = ComputeSomethingExpensive();
future.OnSuccess((position) => Camera.main.transform.position = position);

This code is much more elegant than a usual callback pattern. When thread finishes its work, it calls the Dispatcher to invoke the callback in the main thread. Yes, it sounds scary, but it’s really easy! It’s all about moving the data around between the threads and it is completely safe!

More

There’s much more about the UnityToolbag that I could write about. Yet I won’t, so you have to check it out by yourself. It’s well documented, has examples and the code quality is just great. The Knights of Unity highly recommend!

related
AdvancedGuide
Debugging Web Services With Fiddler In Unity
In order to empower your Unity game with useful features like user accounts, leaderboards,...
1
IntermediateTips
Wrong Import Settings are Killing Your Unity Game [Part 1]
There are many things that may go wrong with your game development. Your models may have too...
2
IntermediateTips
Use Debug.Break() to pause Unity editor from the code
You can pause your game from the editor any time you want. But did you know that you can trigger...
1
Call The Knights!
We are here for you.
Please contact us with regards to a Unity project below.



The Knights appreciate your decision!
Expect the first news soon!
hire us!