Window Management Sample Project

UI Window Management in Unity (Part 1)

If your game contains at least some user interfaces, you will quickly run into the need of manage them in a central place. In our past games we developed a generic window manager that can be used in any project. It takes over the all the loading/unloading of windows and makes sure windows are not opened multiple times.

Basic considerations

The window manager can be used out of the box, but it makes some demands on how you setup your UIs.

One window, one scene

First of all the manager expects that each window is stored in a separate scene. This shouldn’t be a problematic demand as separating the windows in some way is a good idea anyway. The name of the scene is used as the window id by which you open/close a window.

Other than that you are free to setup your window scenes the way you like. Most often you will have a single canvas in it, so there is one root game object. Underneath you design the UI of your window with Unity UI or any other UI system as you are used to.

Hierarchy Main Window Scene
Hierarchy Main Window Scene

Window Manager Singleton

You can easily access the WindowManager  by using its static property WindowManager.Instance . In general I don’t like singletons that much and in fact it doesn’t create a window manager itself. Instead it just stores the first initialized window manager via its Awake()  method.

So you have to make sure to put a WindowManager  script on one of your game objects before using the WindowManager . Additionally make sure that the game object holding the script isn’t destroyed, otherwise the window manager is lost as well.

Implementation

Now let’s dive right into the implementation. You might want to check out the Bitbucket repository and pull the sample project to follow my descriptions easier.

Window Management Sample Project
Window Management Sample Project

Window Manager

As you might have guessed most of the work is done by the WindowManager  class. It has a slim interface to open and close windows:

Internally it contains a list of Window  objects, each storing information about an open window:

Open a window

Let’s have a look now what happens when a new window is opened. The method gets up to 4 parameters, but only the first is mandatory:

  • Window id
  • Window data/context
  • Callback when window was closed
  • Callback when window was opened

The window id has to be unique and has two functions: First of all it acts as an identifier to close the window via its id later on and to avoid opening the same window twice. It is also used to load the window as the window id and the name of the scene the window is saved in have to be the same.

What the OpenWindow  method does is:

  1. Creating a new Window object and adding it to the list of open windows
  2. Starting an asynchronous load of the scene with the name of the window id
  3. Checks if the scene was successfully loaded
  4. Collecting all root Transform s that belong to the loaded scene
  5. Invoking the event and callback

You can check out the steps one by one in the WindowManager.DoOpenWindow  method.

The usage is a very simple one-liner (see the OpenWindow script in the sample project):

Opening a window before Unity 5.3

Before Unity 5.3 the logic and creation of a window was a bit more difficult as there was no chance to get the Transform s that belong to a specific scene. Version 5.3 introduced a new SceneManager  though which makes multiscene editing possible and additive scene loading. Plus each game object has a property to indicate which scene it belongs to ( GameObject.Scene ). Check out the details at http://docs.unity3d.com/Manual/UpgradeGuide53.html.

In Unity 5.2 and lower it was necessary to put a WindowRoot  script on the root game object of your window scenes. This had an identifier which had to be the same as the window id, so the window manager could find the root Transforms of a loaded window/scene.

Closing a window

To close a window, just call the CloseWindow  method and pass the window id or the window object you got by the OpenWindow  method. Additionally a return value could be passed which might be interesting for the listeners of the WindowClosed  event.

After checking if the window is open, the method performs the following steps:

  1. Unloading the window scene
  2. Removing the window from the list of open windows
  3. Invoking the event and callback

As you can see the steps to close just invert the ones to open the window. Thanks to the SceneManager  of Unity 5.3 it’s only some lines of code.

As opening a window, closing it is simple as well (see the CloseWindow script in the sample project):

Showing/Hiding a window

After you opened a window you can use it as you want. A common use case is to hide/show it. This just deactivates/activates the root game objects of a window and can be performed via the Hide() / Show()  methods of the Window class.

Conclusion

The current version contains just the basic functionality to manage UI windows in a project. With it you can easily and cleanly open and close windows and manage them in separate scenes.

In a real project though there are a lot more features that have to be added:

  • Animating the window when it opens/closes
  • Set up the content of a window, using the specified window data/context
  • Testing a window independent of the game it is created for
  • Sharing one canvas for all windows, so you don’t have to do the Canvas settings in each window scene
  • A generic way to open a modal window which can’t be clicked through

Those are just a few requirements for a window manager used in practice. I will cover some of them in future posts, so check back soon. If you have any questions, don’t hesitate to ask! And if you want to have a specific thing about window management covered in the next post about it, let me know 🙂

  • Nifty idea. I never thought about using scenes to store UI layouts and have always done it in prefabs which can be a pain to manage. Thanks for sharing!

  • Is it not more manageable to have all your front end stuff in a single scene, both for simplified visual editing and object to object communication? Also, I noticed there’s always a little load time between scenes. For these reasons I personally try to group stuff into one scene wherever possible.

    • coeing

      Hey Simon!
      Thanks for your comment.
      As always it depends on your project. If you have a user interface which is pretty mingled and has dependencies between the different windows, you should go with a single scene to set it up easier.
      But if there are parts of your user interfaces that are independent of the rest, it makes sense in my opinion to split the setup into multiple scenes. The main advantages are:
      – Easier to manage because of smaller scenes
      – Working with multiple people in parallel on different parts of the user interfaces without getting merge conflicts
      – Easier to through out parts of the UI if not used anymore

      About the lag on loading a new window: You can preload the windows of course and just hide them. This can be decided window by window. So you might just preload the windows which are used nearly all of the time and not preload windows which are just used from time to time (e.g. settings, highscore or Facebook friends window).

      I will write about some more details in further parts of this topic, so hopefully I can persuade you over time 😉 Have some relaxing days!