UI Manager

Having problems organizing UI? Great news, the struggle is over! I will tell you all about the pattern I’m using in most of my projects.

In the majority of cases, we need to see a single UI window at a time, like the main menu, pause menu or in-game window. We might want to bring up a window from many different places in our code. And we want to disable other windows. So we need a method which would disable all windows and enable the one we want and we want to be able to access it from anywhere in the code. Let’s create a new class, call it UIManager and make it a Singleton, using this base class (use Singletons with caution though!).

To switch between different windows more easily, I will make use of enumerators. For now, let’s assume that we will have three windows: the main menu, in-game and pause. Also, we might want to have none. So here is how the UIManager looks:

public enum Window
{
    None,
    MainMenu,
    InGame,
    Pause
}

public class UIManager : Singleton<UIManager>
{
    public void SetWindow(Window window)
    {
        //switch windows here
    }
}

Now, let’s think about the windows. Each window will have different buttons and will behave slightly different than others. So it is a good idea to make a script for each of them.

using UnityEngine;

public class MainMenu : MonoBehaviour
{
}
using UnityEngine;

public class InGame : MonoBehaviour
{
}
using UnityEngine;

public class Pause : MonoBehaviour
{
}

Now let’s declare them in the UIManager like so:

[SerializeField]
private MainMenu mainMenu;
[SerializeField]
private InGame inGame;
[SerializeField]
private Pause pause;

We don’t want other scripts to know about these windows so I made them private. But we still want to assign them through the inspector and that is what the [SerializeField] attribute does: it exposes the field in the inspector.

Activate/deactivate them in the SetWindow(Window window) method and we are done with scripting!

using UnityEngine;

public enum Window
{
    None,
    MainMenu,
    InGame,
    Pause
}

public class UIManager : Singleton<UIManager>
{
    [SerializeField]
    private MainMenu mainMenu;
    [SerializeField]
    private InGame inGame;
    [SerializeField]
    private Pause pause;

    public void SetWindow(Window window)
    {
        mainMenu.gameObject.SetActive(window == Window.MainMenu);
        inGame.gameObject.SetActive(window == Window.InGame);
        pause.gameObject.SetActive(window == Window.Pause);
    }
}

In the Unity editor, create the UI elements, add the scripts, assign the variables and you are good to go!

Unity Hierarchy

Now anytime you need a specific window, you can open it up by simply writing:

UIManager.Instance.SetWindow(Window.MainMenu);

And that’s pretty much it. Know a different pattern or a better way? Anything to improve or fix? Some other suggestions? Perhaps a tip or a request for the next blog post? Let me know in the comments and I will make that happen! You can download the code from the Github and check out the rest of the Extra Tools project!

Leave a Reply

Your email address will not be published. Required fields are marked *