Introduction to Text Engine for Unity: Feedback Controllers

This is part 1 of a two-part introductory tutorial for creating and working with the Feedback Controller feature that ships with Text Engine v1.0, a Unity asset that makes it easy to manage systems of text feedback. In this tutorial, we’ll manually script some C# calls to add a line to the Feedback Controller based on input; in the next post, we’ll use Unity Events to send text to the system. Neat!

So what is a Feedback Controller, anyway?

Here’s what a Feedback Controller looks like:

Basically, a Feedback Controller is any system that manages the creation and behavior of related text elements in our scene.

In this tutorial, I’m going to show you how to call the Feedback Controller in your C# scripts so you can finely-tune when and where a dynamic text system appears on the screen–just like in the gif above.

As will be the case with all the tutorials in this series, I’m assuming you’ve already followed the Text Engine documentation and have both TextMesh Pro and Text Engine imported into your project.

Getting Started

At this point, you should have already Imported both TextMesh Pro and Text Engine, and your hierarchy should look something like this:

Since we want to control the Feedback Controller via C#, the next thing you’ll do is

  1. create a game object,
  2. add it to our scene, and
  3. create a new script on top of it called DemoInput

Unity should look something like this now:

Finally, open up the DemoInput script for editing in your favorite text editor.

Creating a manager reference

The first thing we’ll do is add the textengine namespace to our script:


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using com.lawsonry.textengine;

Next, create a public reference to the scene’s Text Engine Manager. This will be the hub of all our Text Engine operations.


[ExecuteInEditMode]
public class DemoSceneInput : MonoBehaviour {
  public TextEngineManager _TextManager;

You’ll notice that I’m using [ExecuteInEditMode]. This ensures that the reference we’re about to make stays put during changes to our scene.

Let’s go ahead and instantiate our reference variable:


  void Awake() {
   _TextManager = (TextEngineManager)Object.FindObjectOfType(typeof(TextEngineManager));
  }

This is the way I like to do things, since it will give me a public variable that I can manipulate in the editor–but also auto-populates it for me.

Your editor should now look something like this:

With the reference to our Text Engine Manager set, let’s start scripting some text feedback!

Adding lines to a feedback controller

The feedback controller itself is the text lines system we want to interact with. To do that through the Manager reference we just finished setting up, we’ll use a public function called GetFeedbackController(), which returns for us the controller we wish to use.

Note: In Version 1.1 of Text Engine, there will be a way to communicate directly with a specific Feedback Controller. In version 1.0 however, we only have access to one.

Inside our Update function, let’s send a “Hello, world!” when the player presses the “H” key.

  void Update() {
    if(Input.GetKeyDown(KeyCode.H)) {
      _TextManager.GetFeedbackController().AddLine("Hello, World!"); 
    }
  }

As you can see, we’re using the AddLine() function, which, in this version of its overloaded self, takes a simple string and renders it using the default TextMesh Pro settings inside the New Line Prefab object. Nine times out of ten, this is the version of AddLine() you’re going to want to use, but for advanced users, there is the option of passing a TMP_Text object directly.

Here’s what your full script should now look like:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using com.lawsonry.textengine;

[ExecuteInEditMode]
public class DemoInput : MonoBehaviour {
  public TextEngineManager _TextManager;

  void Awake() {
   _TextManager = (TextEngineManager)Object.FindObjectOfType(typeof(TextEngineManager));
  }
 
  void Update () {
    if (Input.GetKeyDown(KeyCode.H))
    {
      _TextManager.GetFeedbackController().AddLine("Hello, World!");
    }
  }
}

If you try to run your scene right now, you won’t see anything. Why? Because our final step is to configure both the New Line Prefab, which is the default settings for new lines in our system, and the Feedback Controller Settings, which define how the system behaves.

First, let’s configure what our system will look like.

Configure the New Line Prefab

Back when you first created the Feedback Controller, a child object of it called New Line Prefab appeared alongside it. This is a TextMesh Pro object that defines the default starting position and font settings for your feedback controller. For example, if I were to make this TextMesh Pro object blue, all my lines would default to blue when they are rendered.

When I wrote Text Engine, I didn’t want to make any assumptions about your canvas size or rendering scales, so I opted for the default rectTransform values shipped with TextMesh Pro. These look like this:

It’s up to you how you want to manage your scales and positions, but what I have seen 90% of the time is Feedback Controllers appearing in the bottom left of games. To do this with these settings, use the following starting values:

There are four total changes I made here:

  • I set Pos X to 90
  • I set Pos Y to -29
  • I inputed some dummy text into the Text Input Box
  • I set the Font Size to 0.35

(Okay okay, I also changed the text color. Sorry.)

Note that the font sizeposition, and width/height are all correlated, so changing one usually means you have to change one or all of the others. Experiment! Go crazy! (But maybe wait until after this demo).

We’re almost done! The final step is to configure the Feedback Controller itself so that the system knows how to behave. Head back to the hierarchy, select the Feedback Controller from the object tree, and let’s get to customizing!

Configure the Feedback Controller

I’ve saved the best for last! The final step in getting your text feedback system up and running is to configure the values of the Feedback Controller. Once you’ve selected the Feedback Controller form the object hierarchy, take a look at the Inspector. You should see something like this:

As you can see, there is an auto-populated reference to our New Line Prefab–that child object of the Feedback Controller we configured in the previous step–and five exciting variables to play around with:

  • Max Lines. This governs the total number of lines the system will process at any given time. If the number of lines on the screen + the one you’re about to make would be greater than Max Lines, the oldest line is immediately killed to make room for the new one.
  • Scroll Speed. How fast the line moves.
  • Alpha Decay. How fast, in seconds, the line disappears.
  • Alpha Decay Delay. How long, in seconds, the line stays at default alpha before the alpha starts decaying at a rate = Alpha Decay.
  • Max Life. The total amount of seconds each line is allowed to stay on the screen, regardless of any other variable.

For a nice, soft movement effect that I’m sure you’ll love, configure your Feedback Controller with the following values:

Now go to your scene and click play. Once your scene is running, hit the H key a few times. If you followed everything in this tutorial, you should see something like this:

Neat!

Now comes the fun part:

Spend the next 20+ minutes experimenting

Experiment with the Feedback Controller settings. What happens if you remove the alpha decay delay? What happens if you change Max Lines? The power to configure the system is yours!

To customize the actual text rendered, you can use rich text HTML tags. As an example, here’s another version of the DemoInput script we created in this tutorial, but with different rendering options showcased when you hit any of the QWERTY keys. (It’s the same script I used to drive the Feedback Controller in the gif at the beginning of this tutorial!)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using com.lawsonry.textengine;

[ExecuteInEditMode]
public class DemoSceneInput : MonoBehaviour {

    public TextEngineManager _TextManager;

    void Awake()
    {
        _TextManager = (TextEngineManager)Object.FindObjectOfType(typeof(TextEngineManager));
    }

    void Update () {
        if(Input.GetKeyDown(KeyCode.Q))
        {
            _TextManager.GetFeedbackController().AddLine("You hit the <color=\"red\">Goblin</color> and did <color=\"green\">15</color> damage.");
        }	
        if(Input.GetKeyDown(KeyCode.W))
        {
            _TextManager.GetFeedbackController().AddLine("The <color=\"red\">Goblin</color> casts <b>Fireball</b>! You take <color=\"red\">20</color> damage!");
        }
        if(Input.GetKeyDown(KeyCode.E))
        {
            _TextManager.GetFeedbackController().AddLine("Goblin says: <i><color=\"yellow\">You'll never take me alive!</color></i>");
        }
        if(Input.GetKeyDown(KeyCode.R))
        {
            _TextManager.GetFeedbackController().AddLine("You cast <b>Magic Missile</b>, dealing <color=\"green\">30</color> damage!");
        }
        if(Input.GetKeyDown(KeyCode.T))
        {
            _TextManager.GetFeedbackController().AddLine("You picked up a <b>health pack</b>. <color=\"green\">+10</color> health.");
        }

        if(Input.GetKeyDown(KeyCode.Y))
        {
            _TextManager.GetFeedbackController().AddLine("This is a plain line.");
            _TextManager.GetFeedbackController().AddLine("This line has a <color=\"red\">red</color> word.");
            _TextManager.GetFeedbackController().AddLine("This line has <i>multiple</i> <b>stylized</b> <u>words</u>.");
        }
  }
}

That’s it!

I hope you’ve enjoyed this tutorial, and are well on your way to making something amazing with the Feedback Controller feature of Text Engine.

If you’re ready for a more Advanced Tutorial, check out Using Unity Events with Text Engine’s Feedback Controller, a follow-up to this tutorial.

As always, please reach out to me if you have any comments, questions, complaints, or concerns.

-Jesse
jesse at lawsonry dot com

Leave a Reply