Unity + Ink: Part 4: Tags and Rich Text

Unity + Ink

The narrative scripting language Ink works with the game engine Unity through a plugin that allows for quickly recompiling, testing, and integrating Ink files in a Unity project.


Tags and Rich Text

Working across this series, the Ink Unity Integration plugin was imported, tested, and then used to build a simple button-based interface. However, there is one more tool Ink has that can be used in Unity: tags.

In Ink, tags are extra code that is ignored. They start with the hash character, #, and run to the end of the line or until another tag is found.

Tags are also attached to the text in front of them. For a single line, its tag would go at the end. For multiple lines, the tags would go at the end of all of text.


"What? Have you never seen a dialogue system before?" #Dan

One way to use tags in Ink when working with Unity, then, is as “speech tags.” These can mark who is saying which words during dialogue.

Parsing Tags

One of the properties not previously discussed so far is currentTags. This is also part of the StoryAPI and, like currentChoices, is populated by a call to the Continue() function.

The currentTags property holds a List<string>. If there are no tags, it will be empty. Therefore, its own property Count can be tested. If its “count” is greater than zero, use the first tag. Otherwise, ignore it.


// Get the current tags (if any)
List<string> tags = story.currentTags;

// If there are tags, use the first one.
// Otherwise, just show the text.
if (tags.Count > 0)
{
   newTextObject.text = tags[0] + " - " + text;
}
else
{
   newTextObject.text = text;
}

Now, if there is a speech tag, it will precede any text and show who is speaking in the interface.

Rich Text

The Ink documentation mentions using tags for things like color or other styling information for text. This could be done, but Unity provides an easier way: rich text.

By default, Text objects have rich text enabled. This means that text can be styled in Ink and passed through to Unity. (In fact, Inky supports a smaller subset of styles as well!)


"What? Have you <i>never</i> seen a dialogue system before?" #Dan

To add emphasis on some text, the <i></i> markup can be used. Added to the text, it will be passed through to Unity and show up as emphasized.

Instead of using tags for colors, the rich text code can be added to Ink directly — or even used directly in Unity itself. For example, to style the color of any speech tags (names), it could be added around them.


 // Load the next block and save text (if any)
 string text = getNextStoryBlock();

 // Get the current tags (if any)
 List<string> tags = story.currentTags;

 // If there are tags, use the first one.
 // Otherwise, just show the text.
 if (tags.Count > 0)
 {
    newTextObject.text = "<color=grey>" + tags[0] + "</color> - " + text;
 }
 else
 {
    newTextObject.text = text;
 }

Marking Options

As a small user interface change, each option (what is shown to the user) can be marked with a number matching its choice index. However, as choosing a zero option might be off-putting for some users, this could be increased by one.


foreach (Choice choice in story.currentChoices)
{
   Button choiceButton = Instantiate(buttonPrefab) as Button;
    choiceButton.transform.SetParent(this.transform, false);

   // Gets the text from the button prefab
   Text choiceText = choiceButton.GetComponentInChildren<Text>();
   choiceText.text = " " + (choice.index + 1) + ". " + choice.text;

   // Set listener
   choiceButton.onClick.AddListener(delegate {
      OnClickChoiceButton(choice);
   });

}

Keep-on Continuing

Along with improving the interface, another change (and function) needs to be made. So far, the function Continue() has been used. This is good if the goal is load content line by line. However, with multi-line content, and those potentially using more rich text markup, this is not as useful.

The function ContinueMaximally() will load content until it finds the next set of choices. In this code, it can be used to load blocks of text until it reaches another choice or the end of the story.


// Load and potentially return the next story block
string getNextStoryBlock()
{
   string text = "";

   if (story.canContinue)
   {
      text = story.ContinueMaximally();
   }

   return text;
}

Styled User Interface

Updating the Ink code, it can now include the following as a much more complex example which also includes usages of rich text markup.


"What? Have you <i>never</i> seen a dialogue system before?" #Dan

* ["No. Of course I have!"]
    "That's good. As this is the beginnings of one. 
    
    "It even has <b>multiple</b> lines of dialogue.
    
    "That's neat, right?" #Dan
    -> DONE

InkExample.cs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.