Monthly Archives: May 2015

A Navigation Helper for Unity

Unity lacks a way to pass parameters to a new scene. If you want to send some game state data to the next level you have several options, such as PlayerPrefs or persistent classes, but they are not always elegant solutions.

I decided to copy NavigationHelper from Windows Store apps. NavigationHelper allows you to send an object when navigating to a new page (scene), like this:

NavigationHelper.Navigate("Level2", myParamater);

myParameter is then retrieved by the new scene when it loads.

I rushed this solution together for a prototype, and I’d love feedback on how it can be improved, as it’s quite basic.

The Code

NavigationHelper static class

This technique requires two parts: the NavigationHelper static class is the part that sends the parameter. It has one public static method and a public static variable of type object.

using UnityEngine;
using System.Collections;

public static class NavigationHelper
    public static object Args;
    public static void NavigateToScene(string sceneName, object args = null)
        if (args != null)
            Args = args;


When you call NavigateToScene() any object in the (optional) args parameter is stored in the static Args variable, and then the requested scene is loaded. This is similar to common workarounds of storing data in PlayerPrefs or static classes, bit is more structured.

If you call NavigationHelper.NavigateToScene() with just the scene name and no parameters it will simply navigate to the scene as if you used Application.LoadLevel().

Receiving the Parameters in the New Scene

When NavigateToScene() is used, the passed parameter gets stored in the static NavigationHelper.Args variable. You can access the parameter from the scene you’ve navigated to. To make this simpler and neater, I decided to create a script that interprets the passed parameter. Here’s the code:

OnSceneLoad script

using UnityEngine;
using System.Collections;

public abstract class OnSceneLoad : MonoBehaviour
    void Awake()
        if (NavigationHelper.Args != null)

    /// summary    ///
    ///Use this method to interpret the arguments received from the navigation helper. Cast the args to the correct type for this scene.
    /// summary
    public abstract void InterpretArgs(object args);

This is an abstract class that inherits MonoBehaviour (so all the usual MonoBehaviour methods are still available). It contains just two members: an implementation of MonoBehaviour’s Awake() method and an abstract method called InterpretArgs().


Awake() is the usual MonoBehaviour method that runs when the scene loads. It verifies that args is not null, then calls InterpretArgs().


It’s up to you what you do in InterpretArgs(). It will run automatically when the scene loads. Typically you will cast the parameter to the relevant type and then do something with it. For example, pass in an object that holds a new game level, and do something like this:

public override void InterpretArgs(object args)
    currentLevelData = (LevelData)args;
    screenHeading.text = currentLevelData.LevelName;
Your ‘receiving’ script needs to inherit OnSceneLoad (replace the : MonoBehaviour on the script with : OnSceneLoad), and you must provide an InterpretArgs() method. This script’s parent GameObject must be active for the receiving to work.

You should only use one OnSceneLoad per scene, but there should be no reason to do otherwise.


It might not seem like it at first, but this method is simpler than the usual workarounds, and is more robust and clean. It’s a simple way to send parameters to a scene in one method call, and a rigid, simple way to receive those parameters. The added rigidity makes it harder to send or received the wrong data.

As I said earlier, this is a first draft of an idea I scrapped together quickly for a prototype. I’d love some suggestions for improving it, such as making it more adaptive to different types of data. Perhaps it should remember parameters for multiple navigations? Arrays? What do you think? Let me know.




Resolution Magic 2D: What it Does

A while back I published a Unity asset called Resolution Magic 2D. Its main feature is to make your game scale to any device regardless of screen resolution or aspect ratio. I am working on a new version and saw an opportunity to show an example of exactly what it does here on my blog.

How does Resolution Magic 2D work?

In a nutshell, it modifies the 2D game camera(s) to ensure a pre-defined area of gameplay is visible (and fills the screen as much as possible) on all screens.

With and without Resolution Magic

With so many devices out there it’s difficult to plan your game to work equally well on all possible resolutions and aspect ratios.

I created a simple scene to show how Unity alters the view at different aspect ratios. I will then show the same scene with Resolution Magic 2D turned on.


Every game is different, so I’ll set out my test scenario. This is important because Resolution Magic will show the content you tell it to show. I’ve tried to keep the example simple rather than realistic.

I have a mysterious sports game played by aliens from the planet Kenney:


The scene as it looks inside the Unity editor


In this example I want the green court area to be as big as possible (i.e. fill up as much screen space as possible). Anything in the yellow area is filler that I only want my player to see if their screen is not the same shape as the green court. In a real game you would probably want some of those spectators visible to add to the atmosphere, but for this example we want to see ALL the green area and as little yellow as possible.


Without Resolution Magic

I designed this game with a 16:9 ratio, and here’s what it looks like on a 16:9 device:

A perfect view of whatever sport those critters are player on 16:9 screens (regardless of pixel resolution). But what about the players who don’t have 16:9 screens?

3:2 (common on iPhone and iPad devices):

Oh no! The goalies have fallen off the screen because it’s not as wide as the game design!

16:10 (common on Windows Phone and Android)

Not as bad as the 3:2, but the edges are still cut off. The game might be playable, but you can’t publish it to an app store in that state!

Unity leaves your content alone, not adapting to the screen it’s on. It’s not good enough!

With Resolution Magic 2D

Here are images from the same scene, but this time with Resolution Magic 2D enabled.

Remember, I told Resolution Magic to make the green area fill as much screen as possible and to show anything in the yellow area only if the screen is a different shape (aspect ratio) to the green court.


Since the game was designed for 16:9 this image looks identical to the one without Resolution Magic.

3:2 (typical iOS)

There’s the magic. Without Resolution Magic the yellow goalies were cut off. Resolution Magic makes sure the entire court area stays on the screen with some of the crowd in the yellow area visible in the ‘dead space’ created by using a different aspect ratio to what you designed. Your player sees everything they should! Like magic.

16:10 (Android, Windows Phone common ratio) res2

Since Resolution Magic works with any screen resolution or ratio, the 16:10 view also makes the court as large as possible without cutting anything off. Some of the crowd is still visible because the game design is wider than the screen.

Bonus: fit to background

Resolution Magic 2D also lets you set a second, larger area of interest so you can further adapt your game. In the following screenshot I have told Resolution Manager to show the entire game area instead of just the court:

The scaling still works, but now you have a view that gives users with larger, higher-resolution screens a more interesting scene, while you can still focus on the court for smaller devices where every pixel matters.

Get the asset

If you want some of that magic in your Unity project, you can get the asset at the Unity Asset Store. It’s only $10, and I’ve only shown the main functionality here – it does more:

  • Automatically fits your chosen content to any screen ratio or resolution
  • All features can be used without scripting
    • Drag-and-drop the prefabs for out-of-the-box functionality
    • Customise behaviour and settings via inspector fields.
  • All features are fully documented (you can download the documentation below and get details of every feature and how to use the asset).
  • All code is fully commented (C#).
  • Simple UI system lets you position UI elements on screen edges and corners, and they stay in their place on any screen.
  • No interference with or from other assets and Unity features
    • Resolution Magic does all its work at the start of a scene. It only affects the 2D camera’s initial position and scale.

Resolution Magic 2D FAQs

I get a few questions about Resolution Magic, some of which are asked all the time.

Q: Does Resolution Magic work on [platform]?

A: Yes. Resolution Magic works completely in Unity code with no fancy addons or platform-specific code.

Q: Does Resolution Magic work with the new Unity UI tools introduced in Unity 4.6?

A: Yes. Resolution Magic doesn’t interact with the UI at all, and the UI doesn’t affect Resolution Magic’s camera scaling algorithms.

Q: What does it do and when?

A: Resolution Magic’s main functionality is to scale and position the camera so that your chosen content is visible to all players and fills the screen as much as possible (based on the screen ratio). It does this at the start of a scene, and once the scene starts Resolution Magic doesn’t need to do anything. You can optionally check for resolution changes (e.g. going from portrait to landscape), which can be useful on some platforms. Resolution Magic will then automatically update the view to match the new screen resolution.

Q: Does it work with Unity 5?

A: Yes. A new Unity 5-specific version has just been released, though the previous version also works in Unity 5, but requires an (automatic) update when it’s installed.

Q: Does it work with 3D games?

A: No. Resolution Magic 2D is designed to modify 2d (orthographic) camera settings. Use in 3D games is not supported at all.