Unity + Ink: Part 2: Working with the Ink API

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.


Working with the Ink API

In the previous part, the Ink function Continue() was used to load and return the next text chunk. It is one of many functions that are exposed as part of using a Story object.

Working with canContinue

The previous example Ink code was not very complicated. It had some initial text and two choices as part of that block.


This is an example Ink file.

* Choice 1
    Nothing here!
    -> DONE
* Choice 2
    Nothing here either!
    -> DONE

Using the Debug.log() function, the first chunk was loaded. However, calling it again would produce an error.


 // Start is called before the first frame update
    void Start()
    {
        story = new Story(inkJSONAsset.text);
        Debug.Log(story.Continue() );
        Debug.Log(story.Continue());
    }

The error shown mentions canContinue. This is a property of the Story object whose purpose is, like its name implies, to expose a value if there is more story to continue or not.

Starting to write the function will prompt its name. Placing the cursor over the name or continuing to type it will show its name and usage.

The canContinue property has a Boolean value if there is more story or not. This is needed before calling Continue() (as it mentions) to make sure the error does not happen again.

As this process of checking canContinue and then calling Continue() is a common action, it should also be made into its own function.


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

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

        return text;
    }

Working with Choices

Working with canContinue exposes if there is more story or not. The function Continue() loads and returns the next text block. Neither of these deal with choices, a central aspect of Ink. For that, the property currentChoices is needed.

For each call of Continue(), the currentChoices property is populated with a List of Choice objects. However, and as its description mentions, once canContinue becomes false, it will often be populated with the last List it loaded.

Moving through the List of Choice objects can be accomplished using foreach().


// Start is called before the first frame update
    void Start()
    {
        story = new Story(inkJSONAsset.text);

        Debug.Log( getNextStoryBlock() );

        foreach (Choice choice in story.currentChoices)
        {
            Debug.Log("The index is " + choice.index + " and its text is '" + choice.text + "'");           
        }

    }

Each Choice object has two important properties: index and text. The order of choices matters. Their index is used to mark which of the choices was chosen. It text property is the option to show to the user.

Choosing Choices

To make a choice, its index is needed. This is used with another function, ChooseChoiceIndex(), that accepts an index that less than the length of currentChoices.


// Start is called before the first frame update
    void Start()
    {
        story = new Story(inkJSONAsset.text);

        Debug.Log( getNextStoryBlock() );

        foreach (Choice choice in story.currentChoices)
        {
            Debug.Log("The index is " + choice.index + " and its text is '" + choice.text + "'");           
        }

        story.ChooseChoiceIndex(0);

        Debug.Log(getNextStoryBlock());

    }

Based on the example Ink story, the calls to Debug.log() would show the initial text, the index and text of each Choice, and then the text of the choice.

Reviewing Ink API

NameTypeDescription
canContinuePropertyIs true if the story can continue to run or false otherwise.
Continue()FunctionReturns the next text block and loads the next choices, if any.
currentChoicesPropertyA List<Choice> of the current choices. (Each entry’s text property contains their text and index its order.)
ChooseChoiceIndex()FunctionSupplying a valid index matching the length of the List<Choice> of currentChoices will consider that entry “clicked.”