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: [code language=”csharp”] NavigationHelper.Navigate("Level2", myParamater); [/code] 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. [code language=”csharp”] 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; } Application.LoadLevel(sceneName); } } [/code] 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

[code language=”csharp”] using UnityEngine; using System.Collections; public abstract class OnSceneLoad : MonoBehaviour { void Awake() { if (NavigationHelper.Args != null) { InterpretArgs(NavigationHelper.Args); } } /// 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); } [/code] 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

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

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: [code language=”csharp”] public override void InterpretArgs(object args) { currentLevelData = (LevelData)args; screenHeading.text = currentLevelData.LevelName; } [/code] 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.

Conclusion

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.      

Leave a Reply

Your email address will not be published.