The Evolution of Aiming in Voyager

Voyager is a game is about science. Not just in the “you’re launching a space probe” sense, but in that the core loop is about experimentation. Make a hypothesis (I need to launch at about 45°), perform the test (3, 2, 1… LIFTOFF), observe the result (missed wide right!), refine the hypothesis (let’s try 30° next time). It took a long time to figure out how to make this process feel natural and intuitive.

In order for it to work, the game needed three things:

  • Feedback: I need to be able to tell how my current aim differs from my last aim.
  • Determinability: If I do the same thing two different times, I should get the same result both times.
  • Precision: I should be able to execute the move as I intended. If I try to launch at an angle of 19°, I should not accidentally launch at 20° or 18° instead.

Solving feedback was the easiest part. The aiming mechanism is very explicit, with an arrow showing the direction and relative power the probe will launch in. Previous launches are shown as dimmer arrows, so the player can easily line up a similar shot and tell how their new one differs. It also straight up tells the user the angle and power of their shot in text, so the values can be written down and reused later. And finally, in-flight probes leave a trail of breadcrumbs, so it’s easy to tell when and how a trajectory diverges from an older one.

Aiming Launch

So much feedback

Continue reading

Dependency Provider

NOTE: I no longer use, or recommend, the DependencyProvider. There are a number of reasons why this is the case, not the least of which because it didn’t work on certain platforms. But by not using it, I found myself missing its ability to cache found references to speed up lookup time, and didn’t need the object instantiation and lifetime management stuff so much. So I kept what I liked, ditched what I didn’t, and ended up with the much simpler DependencyLocator I now use in lieu of FindObjectOfType.

// --------------------------------
// <copyright file="DependencyLocator.cs" company="Rumor Games">
//     Copyright (C) Rumor Games, LLC.  All rights reserved.
// </copyright>
// --------------------------------

using System;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// DependencyLocator class.
/// </summary>
public class DependencyLocator : MonoBehaviour
{
    /// <summary>
    /// Cached DependencyLocator instance.
    /// </summary>
    private static DependencyLocator dependencyLocator;

    /// <summary>
    /// Cache references to component instances.
    /// </summary>
    private readonly IDictionary<Type, Component> instances = new Dictionary<Type, Component>();

    /// <summary>
    /// Locate an instance of the given component type.
    /// </summary>
    /// <typeparam name="T">Type of component to locate.</typeparam>
    /// <returns>Instance of the desired component.</returns>
    public static T Find<T>() where T : Component
    {
        // check whether we have a dependency locator instance
        if (dependencyLocator == null)
        {
            // create a new game object and attach our component
            var gameObject = new GameObject(typeof(DependencyLocator).ToString());
            dependencyLocator = gameObject.AddComponent<DependencyLocator>(); 
        }

        // ask scene dependency locator for a scene instance
        return dependencyLocator.Get<T>();
    }

    /// <summary>
    /// Provide an instance of the given component type by retrieving it from the cache or finding one in the scene.
    /// </summary>
    /// <typeparam name="T">Type of component to provide.</typeparam>
    /// <returns>Instance of the desired component.</returns>
    public T Get<T>() where T : Component
    {
        var type = typeof(T);
        if (!this.instances.ContainsKey(type))
        {
            this.instances.Add(type, FindObjectOfType<T>());
        }

        return (T)this.instances[type];
    }
}

Original post:

Previously, I wrote about the process of locating dependencies in Unity. I enumerated some of the reasons the singleton pattern leads to bad practice, and how good process lead to better, more maintainable code.

And fine, I’ll admit it. I think singletons are ugly and I don’t like them:

TypicalSingleton.Instance.DoSomething(); // gross

Instead, I’d like to offer an alternative, one that doesn’t require a bunch of boilerplate code in every class I want to make globally and performantly accessible. Continue reading

Locating Dependencies

Most components don’t exist in isolation. Sooner or later, they’re going to need to talk to each other, which raises the question of how they should acquire references to one another. In Unity, this is easily accomplished in the editor: expose the type you’re looking for as a public field, then wire it up in the inspector by dragging an instance of the dependency onto the field. I actually really like this approach! It’s essentially a form of dependency injection. This works well for objects in a scene, or relationships between different scripts in a prefab, but it isn’t well suited for items instantiated at runtime. It’s also brittle, since changing the type expected or provided will break the association. These situations call for a different approach to locating dependencies.

Continue reading

Scene Name Attribute

Lots of times, I have scripts that need to be configured with the name of a specific scene. A button might need the name of the menu it loads when clicked, or a door trigger might need to know which level to transition to. Scenes are represented by strings, and therefore are easy to mistype in the Inspector. But in the editor, we have the luxury of a comprehensive list of the scenes in our build, something I leveraged before in my Scene Switch window. Let’s use that same idea to power an attribute (and attribute drawer) to provide a convenient and friendly way to enforce correct scene names every time.

Continue reading

Pool Manager

When I started to understand the importance of object pooling in Unity, I had a hard time finding an implementation that fit my needs. I love the asset store and frequently indulge in purchases that may someday be useful on any one of a dozen ideas I have at the back of my mind – some gamers have a Steam backlog, I have an Asset Store backlog! But in this case, I really just wanted something simple and free. I didn’t need my pool manager to have a ton of fancy features, nor did I want to take on a lot of overhead altering the objects I wanted to pool.

So, I went with a homegrown solution. My implementation simply serves up an instance of the desired prefab: either a reactivated instance from the pool or, if there are no available pooled objects, a newly-instantiated one. This pool manager only manages one prefab each, so it would need retooling to be applicable on a game with lots of different pooled objects. But in situations where just one type shows up frequently and the size of the pool doesn’t increase dramatically over time (tiles in a puzzle game, asteroids in Voyager), it works grand:

// --------------------------------
// <copyright file="UnityPoolManager.cs" company="Rumor Games">
//     Copyright (C) Rumor Games, LLC.  All rights reserved.
// </copyright>
// --------------------------------

using System.Collections.Generic;
using System.Globalization;
using UnityEngine;

/// <summary>
/// UnityPoolManager class.
/// </summary>
public class UnityPoolManager : MonoBehaviour
{
    /// <summary>
    /// Template object to copy.
    /// </summary>
    public GameObject prefab;

    /// <summary>
    /// Whether to reparent the object on pooling.
    /// </summary>
    public bool reparent = true;

    /// <summary>
    /// If reparenting objects, the Transform to parent active objects under.
    /// </summary>
    [HideUnless("reparent")]
    public Transform activeParent;

    /// <summary>
    /// If reparenting objects, the Transform to parent inactive objects under.
    /// </summary>
    [HideUnless("reparent")]
    public Transform inactiveParent;

    /// <summary>
    /// Data structure backing pool.
    /// </summary>
    private Stack<GameObject> pool;

    /// <summary>
    /// Number of instances created of each object type.
    /// </summary>
    private IDictionary<string, int> instanceCount;

    /// <summary>
    /// Initialize script state.
    /// </summary>
    internal virtual void Awake()
    {
        this.pool = new Stack<GameObject>();
        this.instanceCount = new Dictionary<string, int>();
        if (this.inactiveParent == null)
        {
            this.inactiveParent = this.transform;
        }
    }

    /// <summary>
    /// Get an object from the pool if available, otherwise creates a new instance.
    /// </summary>
    /// <returns>An object from the pool.</returns>
    public GameObject Get()
    {
        GameObject poolObject;

        // try to get from pool first
        if (this.pool.Count > 0)
        {
            poolObject = this.pool.Pop();
        }
        else
        {
            if (!this.instanceCount.ContainsKey(this.prefab.name))
            {
                this.instanceCount.Add(this.prefab.name, 0);
            }

            // if pool is empty, create a new instance
            poolObject = Instantiate(this.prefab);
            poolObject.name = string.Format(CultureInfo.InvariantCulture, "{0}({1})", this.prefab.name, this.instanceCount[this.prefab.name]);
            poolObject.transform.SetParent(this.inactiveParent, false);

            this.instanceCount[this.prefab.name]++;
        }

        // reparent if desired
        if (this.reparent)
        {
            poolObject.transform.SetParent(this.activeParent, false);
        }

        // activate object
        poolObject.SetActive(true);

        return poolObject;
    }

    /// <summary>
    /// Release an object back to the pool.
    /// </summary>
    /// <param name="poolObject">Object to release.</param>
    public void Release(GameObject poolObject)
    {
        // deactivate object
        poolObject.SetActive(false);

        // reparent if desired
        if (this.reparent)
        {
            poolObject.transform.SetParent(this.inactiveParent, false);
        }
        
        // return to pool
        this.pool.Push(poolObject);
    }
}

Continue reading

Hide in Inspector

Editor scripting in Unity is one of the more powerful tools available for improving workflow. It’s great to be able to write my own editor window to add new features to the editor, but I’m in love with the flexibility that I get from custom property drawers. Unity has a few built in examples that you’re probably familiar with: SerializeField, Range, and of course, HideInInspector. Simple attributes that can be applied to any field that have a dramatic effect on how those fields get used. Want a field to be private, but editable in the inspector? SerializeField. Public, but not editable? HideInInspector. So helpful!

But of course, there are plenty of other scenarios in which I might want to hide things in the editor. Let’s say I have a class with several fields to configure:

Continue reading

Bindable Values

Let’s say I want Script B to perform some logic whenever a variable in Script A changes. It’s a pretty basic problem, but unfortunately, one that is rarely given the attention it deserves. I’d like to discuss some of the common ways of approaching the task, and share one of the tools I use to make my implementations easier and more consistent.

Continue reading

Custom Script Templates

I hate busywork. Whenever I add a new script to a Unity project, it comes with some requisite amount of whitespace cleanup, re-commenting, and other housekeeping I need to do just to get ready to start writing code. Luckily, that boilerplate code isn’t baked into Unity, it comes from a template that, get this, you can replace.

Continue reading

Setting up a Framework Directory

The first step to creating a great reusable development framework is to have a way of effortlessly sharing code across multiple projects. This is a little trickier than one might expect in Unity. Assets need to be a part of the project directory to be usable. Initially, I tried to follow the Asset Store model, exporting reusable assets as a Unity package and importing that into new projects. Unfortunately, this was a maintenance nightmare. Every minor update required a new export and a gaggle of imports.

I decided a better approach was to use symbolic links. This allowed me to maintain a single Framework folder, and with a tiny bit of setup, for that folder to appear seamlessly in all of my Unity projects.

Here’s how it works:

Continue reading