One simple trick to make TextMesh less pixelated

Tags

,

You’ve probably tried using Unity’s built-in TextMesh, and then recoiled in horror.

Nooo! This is the opposite of what I wanted!

This is the opposite of what I wanted!

There are some advanced techniques to solve this problem, including signed distance shaders or bitmap fonts. If you’re curious and have some time, poke around the net for Unity plugins and shaders supporting those techniques (there are plenty!).

If you’re in a rush, maybe because you’re trying to finish a game jam or because you just want prettier text right now, I have a simple suggestion:

  1. View the TextMesh in the inspector
  2. Scale its transform down to 1% (.01, .01, .01)
  3. Increase its font size to 100
  4. Increase its character size to 10

Just three tweaks, and...

Just three tweaks, and…

Much better!

Much better!

The sad state of Unity Answers

Tags

, , ,

I’m pretty active on Unity Answers. I have been for a long time, and I’d like to continue that. It’s clear, though, that the site isn’t doing very well. The moderation system is lacking, thousands of unanswered duplicate questions pollute search results, many newcomers are unable to find help, and many experienced developers are unable to find fruitful discussion.

How do we fix it? This isn’t a new conversation, but it’s hard to have because there’s no obvious place to have it.

Last week, one user suggested merging Unity Answers into the Stack Exchange network. I posted a bit of an essay in response, and I’m copying that essay here for posterity.


Unity Answers actually used to be hosted via Stack Exchange, back when they had a monthly subscription model. They changed to the current community-driven process in 2010, which ultimately led to the shutdown of the old UA in 2011.

You can find Unity questions on Stack Exchange, but it’s a mess. Some people post to the unity3d tag on Stack Overflow; others post to the Unity tag on GameDev SE.

You can sometimes find threads discussing Unity Answers on various parts of SE meta sites:

The community regulars here are well aware of the content problem on this site, but it’s not a simple problem:

Anyone who hits some karma threshold on here becomes a moderator. There’s no discussion, no election, no record of your moderation activity, and — as far as I can tell — no accountability. Every now and then, we get a new mod who robo-approves every question. Can we stop them? Nope! Can we even tell who it is? Nope! The site continues to limp along as well as it has because some of us try very hard to keep it running, and because UT’s paying the bills.

One problem with Unity is that it attracts a lot of extreme newcomers precisely because it’s so accessible. It’s a little bit like PHP in that regard: it has a bad rep because of the extremely messy projects that beginners tend to create with it, and it’s very easy to find tutorials and articles targeting absolute neophytes, but sometimes very difficult to find anything beyond that.

When people think we’re being “strict” here, they have no idea what it would be like to migrate to Stack Exchange question guidelines. At present, I would estimate the moderators are rejecting 50-75% of incoming questions. SE norms would probably be rejecting well over 90%.

That’s part of what makes SE sites so useful. Because they’ve rejected so much crap, the content that actually makes it to search engines is usually pretty good.

If the newcomers were both willing and able to follow existing documentation, the vast majority of questions on this site could vanish… but that’s the thing: an awful lot of them either can’t, or won’t. More often than not, we serve as human guides to the instruction manual. If we don’t, hundreds of people will walk away from Unity, frustrated because they couldn’t find what they need. Can that be fixed? I don’t know. Part of me thinks it can’t, not with the number of inexperienced people who come through. It’s like fighting the tide.

Newer tutorials seem to have helped. I’ve thought about going through and deleting a few hundred (thousand?) old, useless questions. Without some community mandate, though, I feel a bit uncomfortable with that.

I do wish there were a better place for expert discussion of Unity, though.

My impression is that there isn’t critical mass to get a Unity-specific site through SE’s Area51 process. The GameDev SE is my current port of call, but even that’s just a trickle. Blogs and books are a nice respite, sometimes.

How to Lerp like a pro

Tags

,

I see this sort of thing far too often:

transform.position = Vector3.Lerp(startPos, endPos, Time.deltaTime);

The person posting it is usually convinced that Vector3.Lerp is “broken”, but the real problem is that they’re not using it correctly.

Lerp, short for “linear interpolation” does one very simple thing: given two values, x and y, it returns a value that is t percent between them. If you expect the output to change, the arguments you pass in need to reflect that!

In the example above, it doesn’t make sense to just pass in Time.deltaTime, because that’s only the time that passed during the most recent frame. If your game is running at a constant 50fps, that’s always going to be 0.02.

We’ll get better results if we let that timer accumulate over multiple frames.

Something like this should get the point across:

    public class LerpExample : MonoBehaviour {
        float lerpTime = 1f;
        float currentLerpTime;

        float moveDistance = 10f;

        Vector3 startPos;
        Vector3 endPos;

        protected void Start() {
            startPos = transform.position;
            endPos = transform.position + transform.up * moveDistance;
        }

        protected void Update() {
            //reset when we press spacebar
            if (Input.GetKeyDown(KeyCode.Space)) {
                currentLerpTime = 0f;
            }

            //increment timer once per frame
            currentLerpTime += Time.deltaTime;
            if (currentLerpTime > lerpTime) {
                currentLerpTime = lerpTime;
            }

            //lerp!
            float perc = currentLerpTime / lerpTime;
            transform.position = Vector3.Lerp(startPos, endPos, perc);
        }
    }

You could create an empty scene, drop in a cube, attach this script, and see it in action.

The variable perc is used where Time.deltaTime used to be. What is perc? It’s a number between 0 and 1, representing our progress through the Lerp.

If you’re curious, check the result if you change lerpTime or moveDistance.

Lerp everything

Unity provides helper functions for interpolating many different values.

  • Mathf.Lerp
  • Vector3.Lerp
  • Color.Lerp

At the end of the day, though, Mathf.Lerp is all you need; the others are just convenience methods on top of that. It’s easy enough to write your own Lerp function for any class or data you might need to interpolate.

In the specific case of quaternions, which Unity uses to represent rotation, there’s even a Slerp or “Spherical Lerp”.

Any time you have two values, and you’d like to smoothly transition between them? Interpolation is your friend!

Beyond Lerp

What if we passed Lerp a t that wasn’t just a straight percentage? What if, instead of a straight line graphed between two points, we wanted some sort of curve? Our input must remain between 0 and 1, but there are many functions that accomplish that.

For example, we could “ease out” with sinerp:

float t = currentLerpTime / lerpTime;
t = Mathf.Sin(t * Mathf.PI * 0.5f);

interp-sinerp

Or we could “ease in” with coserp:

t = 1f - Mathf.Cos(t * Mathf.PI * 0.5f)

interp-coserp

We could even create exponential movement:

t = t*t

interp-quad

Multiplying t by itself has an interesting quirk: so long as t is between 0 and 1, multiplying t by itself any number of times will always produce a number that is also between 0 and 1.

Smoothstep

The multiplication property mentioned above is the core concept behind some interpolation methods which ease in and ease out, such as the famous “smoothstep” formula:

t = t*t * (3f - 2f*t)

interp-smooth

Or my personal favorite, “smootherstep”:

t = t*t*t * (t * (6f*t - 15f) + 10f)

interp-smoother

So smooth! (Couldn’t resist.)

Many of these extra formulas I’ve mentioned aren’t included with Unity, but that just gives you the freedom to use any function you can find or create.

Make it breathe

What about a Lerp that never ends?

Robert Yang once said, “Sometimes I wish I could animate every single thing in my game with a sine wave.”

Some games introduce a slight “head bob” while the player is running. Other games need a gentle bob for the main menu camera. I’ve seen lights that “snore”, fading in and out. Whatever the case, I just want to point out how fantastically useful wave functions can be — their input domain is infinite, so they never have to end, and their output range is both narrow and constant, so they’re easy to control.

For example, this script makes an object slowly move up and down, according to a sine wave:

    public class BreatheSimple : MonoBehaviour {
        Vector3 startPos;

        protected void Start() {
            startPos = transform.position;
        }

        protected void Update() {
            float distance = Mathf.Sin(Time.timeSinceLevelLoad);
            transform.position = startPos + Vector3.up * distance;
        }
    }

Adjusting the sine wave gives us more control:

    public class Breathe : MonoBehaviour {
        Vector3 startPos;

        public float amplitude = 10f;
        public float period = 5f;

        protected void Start() {
            startPos = transform.position;
        }

        protected void Update() {
            float theta = Time.timeSinceLevelLoad / period;
            float distance = amplitude * Mathf.Sin(theta);
            transform.position = startPos + Vector3.up * distance;
        }
    }

Amplitude controls how far the object moves; period controls how quickly it does so.

interp-sineparams

A player’s head bob might call for small amplitude and a short period. A menu camera’s slow breathing might call for an extremely long period, or movement on multiple axes at varying rates.

As long as you can sort out the math, you can get whatever behavior you want.

What happens if you take only the absolute value of the sine wave? Upward-only bouncing.

What happens in you clamp the sine wave’s output between 0 and 1? Upward-only bouncing with a pause between bounces. Can you see why? Draw the clamped curve yourself and it should become clear.

What if you clamped that wave’s output between 0.6 and 1? Would you get a sort of “throb” motion? Could that be useful to scale an alert in your UI?

If you want to get really fancy, you could even use an animation curve to manage your Lerp params.

I’ve written some pretty esoteric curve and wave functions. Don’t be afraid to mix it up.

In closing

Lerp is an easy and powerful function with many applications.

One of the first plugins I ever wrote was a camera manager that interpolates between various zooms and positions. I’ve also used interpolation to manage material parameters, UI animation, physical forces, audio volume, simple cutscenes, and more.

This is one of those hammers that turns up more and more often, once you know how to use it.

If you don’t want to write a lot of code, or want a head start, plugins like iTween, GoKit, or Hotween add lots of extra interpolation support to Unity.

High precision input timing

Tags

, ,

I’ve heard some developers complain that Unity only updates input once per frame, and that they find themselves in some circumstance where they need more accurate information about when exactly a key was pressed.

As it turns out, there is a hidden way to get at this information: Unity’s Event class.

From the scripting reference:

Events correspond to user input (key presses, mouse actions), or are UnityGUI layout or rendering events.

For each event OnGUI is called in the scripts; so OnGUI is potentially called multiple times per frame. Event.current corresponds to “current” event inside OnGUI call.

If you’re the sort of person who avoids OnGUI whenever possible, you probably never knew about this feature!

This gets us a function call for each key press (and release), among other things. Now, we just need timing information. Lucky for us, Time.realtimeSinceStartup still returns useful data between frames.

You now know which key was pressed and exactly when it was pressed. It’s easy enough to pass that data along to other parts of your game; what you do with it after that is up to you.

Here’s a quick-and-dirty proof of concept: HighFreqInput.cs.

 

 

Flying Over the Influence, Alpha build!

Tags

,

Flying Over the Influence screenshot

Play the alpha build here.

Flying Over the Influence, a drunken flight simulator, is coming soon for PC, web, and Android.

Matt Shouse and I started work in January for Global Game Jam 2014. The prototype’s source is available on GitHub, if you’re curious. Try the new alpha, and you’re sure to see that we’ve made a lot of progress in just a few short weeks!

Coroutines in the editor

Tags

Conventional wisdom says that coroutines only run while your game is playing. If you want to use a coroutine in an editor script, you’re just out of luck. As it turns out, that’s not quite entirely true.

You can manually iterate the coroutine.

After all, each coroutine is represented by an enumerator, and enumerators can be advanced by calling their MoveNext() function.

Bear in mind that coroutines are often waiting for a reason (say, WWW loads), whether it’s a change in state, time, or some async operation. Sometimes, though, I find myself writing a coroutine that spreads work over multiple frames for the sole purpose of avoiding performance hiccups.

As an example, I once wrote a game that built each level randomly. During gameplay, the level is built by a coroutine that takes several frames. When testing level builds in the editor, I couldn’t wait for frames because the game wasn’t running.

Instead of writing the same function twice, I write one coroutine and provide two hooks: one waits politely for the coroutine to finish on its own, the other forces it to finish immediately.

Here’s a simplified example:

void RuntimeBuild() {
    StartCoroutine(Build());
}

void EditorBuild() {
    IEnumerator e = Build();
    while (e.MoveNext());
}

IEnumerator Build() {
    Debug.Log("Started build");

    for (int i=0; i<10; i++) {
        Debug.Log(i);
        yield return null; //wait one frame
    }

    Debug.Log("Build finished!");
}

Loading screen tutorial

Tags

It’s a common enough feature request: add a loading screen between levels. This isn’t quite as easy as you might expect, but it’s pretty quick once you’re familiar with Unity’s scripting features.

Because Unity allows us to control the way levels are loaded, we can put up a very simple “transition” scene while we wait for a bigger level to load. The transition scene could be just about anything, but here are some ideas:

  • Completely empty, except for an OnGUI hook showing some text.
  • An orthographic camera staring directly at a textured quad.

If you have Unity Pro, you could even take advantage of async level loading to create a quick animation or mini-game; otherwise, I’d recommend you stick with something that renders one frame (think “splash screen”).

Point is, the particular contents of the transition scene don’t matter very much. This tutorial just gets you as far as having one.

Creating a transition scene

We’re going to need a transition scene. I strongly recommend keeping it simple, so that it can load quickly and won’t slow down the more expensive target scene load.

  • Create and save an empty scene, name it “Loading”.
  • Add the scene to your build settings (File > Build settings…).
  • Populate the scene with some simple stuff.

As I mentioned above, I’m a fan of the ortho camera staring into one or more textured quads. You could whip up some scripts to show a semi-randomized texture, show some helpful tips, or whatever you want.

For the purpose of this tutorial, we’ll get up and running with the simplest possible thing:

public class LoadUI : MonoBehaviour {
    public Color backgroundColor = Color.black;
    public Color textColor = Color.blue;
    public string message = "Loading...";

    void Start() {
        Camera.main.backgroundColor = backgroundColor;
    }

    void OnGUI() {
        //cache and update GUI settings
        Color cachedColor = GUI.contentColor;
        GUI.contentColor = textColor;

        //draw label
        float width = 60f;
        float height = 20f;
        float left = Screen.width / 2 - width;
        float top = Screen.height / 2 - height;
        Rect rect = new Rect(left, top, width, height);
        GUI.Label (rect, message);

        //restore GUI settings
        GUI.contentColor = cachedColor;
    }
}

Attach that script to something in your scene and press play. You should see the loading message. Nothing else will happen (yet).

Creating a script hook

Most people switch levels by calling Application.LoadLevel. Since we want to control the process, we need to provide a single hook for other scripts to call. We’ll make a new class called LevelManager that’s just simple enough to keep working:

public class LevelManager {
    public static void Load(string name) {
        Application.LoadLevel(name);
    }
}

This is just a wrapper, but it gives you a single access point: all other level switching should be done by calling LevelManager.Load, so that you can swap it out later without breaking the project.

Here’s a very simple test script:

public class LevelManagerTest : MonoBehaviour {
    void Start() {
        Invoke("TestLoad", 2f);
    }

    void TestLoad() {
        LevelManager.Load("SomeOtherLevel");
    }
}

The above will wait two seconds before calling LevelManager.Load. You should probably replace "SomeOtherLevel" with the name of an actual level that exists in your project. Or, if you’re in a hurry, use Application.loadedLevelName to reload the current level.

As an aside, remember that Application.LoadLevel can only load levels which are configured in your build settings.

A single-frame loading screen

This next step will get us to render one frame in the transition scene, then load the target scene. While performing a blocking load, Unity displays the last rendered frame; in our case, this is an advantage.

We’re going to start mixing static and instance members of the LevelManager class. If you don’t understand the difference, you might want to look it up.

We’re also going to use a coroutine. They enable us to create asynchronous functions which can execute across multiple frames.

Let’s flesh out the LevelManager class a bit more:

public class LevelManager : MonoBehaviour {
    public static void Load(string name) {
        GameObject go = new GameObject("LevelManager");
        LevelManager instance = go.AddComponent<LevelManager>();
        instance.StartCoroutine(instance.InnerLoad(name));
    }

    IEnumerator InnerLoad(string name) {
        //load transition scene
        Object.DontDestroyOnLoad(this.gameObject);
        Application.LoadLevel("Loading");

        //wait one frame (for rendering, etc.)
        yield return null;

        //load the target scene
        Application.LoadLevel(name);
        Destroy(this.gameObject);
    }
}

Reminder: unless you have access to Pro’s async loading, the transition level will freeze during the load. Keep it simple.

Try your LevelManagerTest script again. You should notice that your loading scene gets used!

Introduction

Unity is a fantastic game engine, for hobbyists and indie developers alike. It’s easy to find scores of tutorials for newcomers, but much harder to find resources targeting skill levels even slightly higher than that.

I won’t pretend to be an expert at programming graphics engines, but I know my way around Unity after working with it for a few years, including professional work at Techtonic Games and student work at Chico State Game Studios.

My posts will focus on writing C# code for Unity, ideally for an audience with some background in computer science or software engineering.

I’ve been active on Unity Answers, and I’ve helped plenty of people in other forums or meetups; I’m hoping this blog can be another way to help people learn about Unity.