Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Unity stonks

The Best Advice I Wish I Had When I Started Game Development

Today marks seven years since I embarked on my journey with the Unity game engine as an independent developer. It’s not my primary profession; rather, it’s a deep-seated passion.

Here’s the most invaluable piece of advice I can offer to save you time in your game development endeavors. This advice is universal, but it carries particular weight in the realm of video games.

Every game has its unique features, but they all progress through distinct stages. For instance, in a game where virtual currency comes in the form of gold coins, you typically start with zero and earn coins by slaying monsters, allowing you to purchase equipment.

Epic seven secret shop

Epic seven – secret shop

In another type, like a Mario-style platformer, you begin at the level’s start, but as you progress, you can reach checkpoints to avoid restarting from the beginning after a misstep.

Mario world checkpoint

Mario world – checkpoint

Hence, as developers, we constantly need to adjust these states to conduct various tests. Taking the previous examples, it’s far simpler to begin the game with, say, 1000 coins to examine if your purchase system functions effectively. This avoids the need to play to earn coins and then buy equipment. Similarly, for the platformer, it’s more convenient not to start from the level’s beginning every time when testing various segments.

This advice is straightforward: ‘Don’t be Lazy.’ By this somewhat candid expression, I mean that we must build bridges to make our lives easier instead of repeating manual tasks. When testing a specific feature, focus on that aspect alone rather than testing the entire process leading up to it; this approach can save you significant time.

At first, it may be tempting to directly modify different states in the code or inspector. For example, if you have a class with a property that stores your gold, you can change the value in the inspector:

using UnityEngine;

public class GameBootstrap : MonoBehaviour
{
    public int gold;
}

Unity Monobehaviour Inspector

This might seem like a good initial solution to save time instead of playing to earn that gold. However, in reality, leaving this field as it is isn’t a common practice. Instead, you’d prefer to call a function (or directly modify the getter) to alter the coin value and then invoke an event:

using UnityEngine;

public class GameBootstrap : MonoBehaviour
{
    public int Gold { get; private set; }

    public UnityAction OnGoldChange { get; set; }

    // we create a static instance of the class for an easier management.
    public static GameBootstrap Instance { get; private set; }

    private void Awake()
    {
        Instance = this;
    }

    public void AddGold(int value)
    {
        Gold += value;
        OnGoldChange?.Invoke(Gold);
    }
}

But with this code, you can’t change the gold value directly in the inspector. Several solutions exist to address this issue, but the most suitable one in this case is to create a ‘Dev Mode’ bar where you can modify the game’s state.

Let’s start by creating our user interface. Construct a canvas with a container (gameObject with image component) and add an input with a button. Then, create a ‘DevBar’ class to interact with the UI, making sure not to place this file in an ‘Editor’ folder.

#if UNITY_EDITOR
using UnityEngine;
using TMPro;
using UnityEngine.UI;

public class DevBar : MonoBehaviour
{
    [SerializeField]
    private TMP_InputField _inputCoinField;

    [SerializeField]
    private Button _buttonCoin;

    public static DevBar Instance { get; private set; }

    private void Awake()
    {
        Instance = this;
        // We need the devBar, even if we change scene
        DontDestroyOnLoad(this);
    }

    private void Start()
    {
        // I always like to clean events before add one.
        _buttonCoin.onClick.RemoveAllListeners();
        _buttonCoin.onClick.AddListener(SubmitCoin);
    }

    public void Toggle()
    {
        gameObject.SetActive(!gameObject.activeSelf);
    }

    private void SubmitCoin()
    {
        // Check if input text, is a valid integer
        if (!int.TryParse(_inputCoinField.text, out int coin))
        {
            Debug.LogError("Cant add coins");
            return;
        }

        GameBootstrap.Instance.AddGold(coin);
    }
}
#endif

You’ll notice that this class starts with the condition ‘#IF_UNITY_EDITOR’ to ensure that this script will never be present in a build. If you’d like me to cover how to implement this ‘DevBar’ in a build in a follow-up, feel free to let me know in the comments.

Next, add this MonoBehaviour to your canvas. Ensure that it has a high rendering priority so that the DevBar always appears in front of your other UI elements. Link the button and input elements in the hierarchy. You can also assign the ‘EditorOnly’ tag to the canvas to prevent this gameObject from appearing in a build (in case you forget to remove it from a scene).

Unity Canvas Inspector

Now, deactivate the gameObject containing your canvas, set it as a prefab, and you can place it in a ‘Prefab’ folder for better organization. Finally, remove the canvas from the scene.

To open this DevBar during gameplay, create a script named ‘MenuBarEditor’ in the ‘Editor’ folder. I’ll provide a link to the MenuItem documentation.

using UnityEditor;
using UnityEngine;

public static class MenuBarEditor
{
    // menu path of devBar, TAB is used as shortkey
    const string DevBarName = "Utility/Dev Bar _TAB";

    [MenuItem(DevBarName)]
    public static void ToggleDevBar()
    {
        // we can't open the devBar in editor
        if (!Application.isPlaying)
        {
            return;
        }

        // first Initialisation
        if (DevBar.Instance == null)
        {
            InvokeDevBar();
            return;
        }

        Toggle(DevBar.Instance);
    }

    private static void InvokeDevBar()
    {
        // load the prefab, put the right path
        var prefabDevBar = AssetDatabase.LoadAssetAtPath<DevBar>("Assets/Prefab/DevBarCanvas.prefab");
        var devBar = Object.Instantiate(prefabDevBar);

        Toggle(devBar);

        // When exiting we want the checked on menu to disapear
        Application.quitting += OnQuitting;
    }

    private static void Toggle(DevBar devBar)
    {
        devBar.Toggle();

        // add or remove checked for a better visualisation
        Menu.SetChecked(DevBarName, devBar.gameObject.activeSelf);
    }

    private static void OnQuitting()
    {
        Application.quitting -= OnQuitting;
        Menu.SetChecked(DevBarName, false);
    }
}

Thanks to this code, you can open the DevBar either by pressing the TAB key or through the ‘Utility/Dev Bar’ menu.

Unity devbar menu

You can now easily add gold during your game.
This was just one example, but you can apply this principle to far more complex and time-consuming scenarios depending on your game’s features.

Leave a Reply

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