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

Global Game Jam 2015

This year was my second time participating in the Global Game Jam, and my third 48-hour jam overall. Along that storied history, I’ve learned a few things about how to be an effective and successful (defined here as ending the jam with a playable prototype that isn’t embarrassing for something made in a weekend) jammer. Here are some of those learnings, distilled into handy, categorized-tip form.

Continue reading

Fast Scene Switching in the Unity Editor

One of the many powerful features of Unity is the ability to write extensions for the editor. As I worked on Voyager: Grand Tour, I found myself doing a number of repetitive tasks – not terribly time-consuming individually, but frustrating enough in aggregate to get me curious about optimizing my workflow with software. Still, I put it off, figuring I didn’t have time to divert toward extraneous development to save a few seconds here and there.

Well, a few months ago, a friend of mine by the name of Zach Aikman gave a talk on Unity Editor extensions at the local Unity user group meetup. His detailed overview provided more than enough information to get me started, and the first thing I did when I got home was to whip up a solution to a problem that, while small, had nagged me frequently while developing Voyager: quickly switching between scenes.

In my game, I split my content and menus up into a lot of scenes that I frequently had to switch between, which in the default Unity editor meant a lot of pointlessly scrolling around in the project view. This simple editor window grabs a list of scenes from the Build Settings and presents them as buttons for fast switching. It’s dead simple, but it genuinely saves me time and frustration every day, and I’m happy to share it with anyone who’s interested!

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

using System.IO;
using UnityEditor;
using UnityEngine;

/// <summary>
/// SceneSwitchWindow class.
/// </summary>
public class SceneSwitchWindow : EditorWindow
{
    /// <summary>
    /// Tracks scroll position.
    /// </summary>
    private Vector2 scrollPos;

    /// <summary>
    /// Initialize window state.
    /// </summary>
	[MenuItem("Tools/Scene Switch Window")]
    internal static void Init()
    {
        // EditorWindow.GetWindow() will return the open instance of the specified window or create a new
        // instance if it can't find one. The second parameter is a flag for creating the window as a
        // Utility window; Utility windows cannot be docked like the Scene and Game view windows.
        var window = (SceneSwitchWindow)GetWindow(typeof(SceneSwitchWindow), false, "Scene Switch");
        window.position = new Rect(window.position.xMin + 100f, window.position.yMin + 100f, 200f, 400f);
    }

    /// <summary>
    /// Called on GUI events.
    /// </summary>
    internal void OnGUI()
    {
        EditorGUILayout.BeginVertical();
        this.scrollPos = EditorGUILayout.BeginScrollView(this.scrollPos, false, false);

        GUILayout.Label("Scenes In Build", EditorStyles.boldLabel);
        for (var i = 0; i < EditorBuildSettings.scenes.Length; i++)
        {
            var scene = EditorBuildSettings.scenes[i];
            if (scene.enabled)
            {
                var sceneName = Path.GetFileNameWithoutExtension(scene.path);
                var pressed = GUILayout.Button(i + ": " + sceneName, new GUIStyle(GUI.skin.GetStyle("Button")) { alignment = TextAnchor.MiddleLeft });
                if (pressed)
                {
                    if (EditorApplication.SaveCurrentSceneIfUserWantsTo())
                    {
                        EditorApplication.OpenScene(scene.path);
                    }
                }
            }
        }

        EditorGUILayout.EndScrollView();
        EditorGUILayout.EndVertical();
    }
}

Now also available on the Unify Community Wiki.

Voyager Level Design

I’d like to share a bit of my process of creating levels for Voyager.

Most of the time, a level starts as an idea for a technique I’d like the player to learn, or a cool experience I want them to have. For instance, a gravitational slingshot is a core mechanic in the game, but at some point I’d like players to figure out how to chain multiple slingshots together to get past several obstacles. I also like the idea of weaving between planets – sort of a space slalom. So, there should be a level between learning how to do a slingshot maneuver and being expected to string them together to win where the chaining concept is introduced and presented in a fun way.

Unity 2013-05-15 13-58-11-28

The “Gas Giants” level does just that. It features an arrangement of planets that suggests (but does not require) a winding, between-the-gates sort of trajectory. Jupiter blocks a direct route to the target Uranus, and Saturn gets in the way of a simple slingshot around Jupiter on the right-hand side. Once I’ve got the general arrangement of planets figured out, it’s time to run the Path Predictor.

Path Predictor is one of the more important tools in my design arsenal. It simulates the trajectory for a launch, given an angle and power level (and delay, for levels with a timing element). After running it, I end up with a visualization like this.

Unity 2013-05-15 13-38-15-39

Though it’s usually more helpful to filter out angles that result in crashes and misses and just focus on successful paths.

Unity 2013-05-15 13-37-26-35

This view makes it clear that there are a few viable slalom trajectories, but it’s also quite easy to just bypass that experience and slingshot straight to the target. I need another way to reinforce the weaving path as something worth attempting. That’s where star placements come in.

Unity 2013-05-15 13-37-26-35_stars

In this level, there are a few points where the slalom trajectories intersect, providing natural, ideal locations for stars. This ensures there are multiple viable solutions. And of course, players will experiment with different power levels (or, with the “expert” controls enabled, fractional angles) that could surprise even me.

Of course, at this point the level is still far from done. It needs to be playtested for fun and difficulty before making the cut in the finished product!

Dark Side of the Jam

Last weekend, I organized and participated in Seattle’s satellite “Dark Side of the Jam,” a space-themed game jam which the Academy of Interactive Entertainment graciously agreed to host. Our mission was to build a game (using at least one NASA asset) in just 48 hours.

Our satellite jam started at 6pm on Friday, with participants filing in until around 7:30. We kicked off the event with some inspirational words by Dan Dixon, the creator of Universe Sandbox, and then started brainstorming ideas. As more people arrived, we decided to split into two teams, but to let everyone collaborate between the two projects (especially our artists and sound designer!).

We tossed around a number of exciting and ambitious ideas, from a game about discovering exoplanets with real-world problem solving elements (along the lines of Foldit) to one about engineering your own rockets (think Kerbal Space Program).

Two projects gathered the most attention and excitement, though. One was a game about driving the Lunar Rover around to pick up your astronaut bros. The other, and the one I worked on, is called Seven Minutes to Heaven. The game is about the time delay involved in communicating with a rover on Mars. While that delay can range from a couple of minutes to nearly half an hour, the name is an allusion to Curiosity’s Seven Minutes of Terror.

dsj_screenshot

The game is played by selecting commands from the control panel’s arrows to drive the rover, a camera to get a better view of the surrounding area, and the drill to take a sample from the surface. The objective is to search for elements of interest (Hydrogen, Helium, Carbon, and Oxygen) within the time limit. The amount of each element in a square is communicated through an emission spectrum. The player can cross-reference this against known spectra to make decisions about where the most productive areas to drill are. It’s a little like Minesweeper, if you had to wait a while for your moves to take effect, the numbers were in code, and you only had until the sun goes down to finish playing. Also it’s on Mars.

Because we only had 48 hours to build the entire game, some features did not make it into the finished product before the end of the jam. With more time, we would have given players specific objectives (for example, find at least 6 units of Carbon and 2 of Helium) and better explained the controls and emission spectra in-game. We also didn’t get in all the art and sound effects produced by our teammates, or have much time for testing and play balance.

Even so, I’m really proud of how complete and polished the game ended up. More than that, I had a great time getting to know and work with a bunch of awesome people.