Ink

The Dialogue System can tie into Inkle's Ink Integration for Unity.

Ink copyright © Inkle Studios.

About Ink Integration

Ink is a narrative scripting language created by Inkle Studios. You can read about Ink here:

https://www.inklestudios.com/ink/

Unlike the other third party file formats that use the Dialogue System's in-editor import tools to create dialogue databases, when working with Ink the Dialogue System uses Ink as the engine that parses Ink files and runs them. Your Ink files can use the Dialogue System's ShowAlert and quest control functions, and the Dialogue System can get and set Ink global variable values.

Example Scene

The example scene lets you play two conversations.

  • "story" is a version of the Ink-Unity integration's example story with these additions:
    • External Functions to interface with the Dialogue System.
    • Actor Tags to disambiguate some lines.
    • A variable "wagerAmount" that gets set during the story. You can set a watch on this variable in the Dialogue Editor if you want to see it change.
  • "TheIntercept" is a copy of Inkle's sample story for Ink.

Ink Setup

  1. Import Inkle's Ink Integration for Unity. You can get it here: https://www.assetstore.unity3d.com/en/#!/content/60055
  2. Import the unitypackage Plugins ► Pixel Crushers ► Dialogue System ► Third Party Support ► Ink Support.
  3. If you want to specify entrypoints using the full file paths of your Ink stories – and not just the story, knot, and stitch – then add the scripting define symbol INK_FULLPATHS. To do this, select menu item Edit → Project Settings. In the Player → Other Settings section, add INK_FULLPATHS to the Scripting Define Symbols field, separating it from any existing content using semicolon.
  4. Add a Dialogue System Ink Integration component to the Dialogue Manager.

    • Assign your Ink stories (JSON files) to the component's Ink JSON Assets list. These stories will be added to the Dialogue System's runtime environment when the component starts. To add additional stories at runtime (e.g., user content, or downloaded from a server), use the DialogueSystemInkIntegration.AddStory(title, json) method.
    • If you want to start each Ink story from the beginning each time you play it, tick Reset State On Conversation Start.
    • Explore the other options, such as Force Response Menu For Single Choices by mousing over them for tooltips.
  5. To include the states of the Ink stories in the Dialogue System's save data, add an Ink Saver component to the Dialogue Manager.
  6. Create a dialogue database, which can be empty, and assign it to the Dialogue Manager. This will silence the Dialogue System's warning about no database being assigned. The Dialogue System Ink Integration component will create another database at runtime and add it to the Dialogue System's runtime environment.

You may want to add the following to the database:

  • Actor 1: "Player" - the player actor used in response menus.
  • Actor 2: "Story" - the default actor used in subtitles.
  • Quests, if your game has any.

Note: Previous versions of this integration used a third actor for the player speaker. This is no longer necessary. Player lines are now assigned to the player actor.

Actor Prefix

If you tick the Dialogue System Ink Integration's Actor Names Precede Lines checkbox, you can specify actor names at the beginning of lines, separated by a colon, as in:

Monsieur Fogg: 'A wager,' he replied.

How to Start Conversations

You can use all of the Dialogue System's regular triggers, scripting API calls, and visual scripting actions to start Ink stories as conversations.

Since the stories are added at runtime, you'll need to enter their names manually in Dialogue System Triggers' Conversation title field. Or, if you prefer, you can create a dummy database containing empty conversations with the same titles as your stories, assign this database to your Dialogue System Trigger's Reference Database, and select the conversation from the dropdown menu. (Don't add this dummy database to the Dialogue Manager.) The Reference Database is not used at runtime; it's used only to populate the dropdowns in the editor.

Note: This integration is designed to run one Ink story (conversation) at a time. You can run other, non-Ink conversations simultaneously with an Ink conversation, however.

Start At Knot

If you want to start a conversation at a specific knot or a stitch within a knot, add a DIalogue System Ink Trigger component. This component is like the regular Dialogue System Trigger except it has an Ink-Specific section that lets you specify an optional knot (or knot.stitch) to start at.

Start Conversation Manually

To start a conversation manually, call DialogueManager.StartConversation as usual. If you want to start a conversation at a specific knot or stitch, call DialogueSystemInkIntegration.SetConversationStartingPoint("knot") first. For example:

DialogueSystemInkIntegration.SetConversationStartingPoint("admitted_to_something");
DialogueManager.StartConversation("TheIntercept");

lastStartingPoint

The property DialogueManager.lastConversationStarted returns the name of the last conversation/Ink story started. Similarly, DialogueSystemInkIntegration.lastStartingPoint returns the knot that the last conversation started at. If the conversation started at the beginning of the story, lastStartingPoint will be blank.

How to Start Barks

Use a Dialogue System Ink Trigger component to start a bark. In the Ink-Specific section, specify the knot (or knot.stitch) to bark.

Alternatively, you can use a Bark Ink On Idle component to bark from an Ink story. In the Ink-Specific section, specify the knot (or knot.stitch) to bark. Note:

  • If the Bark Order is set to Sequential, subsequent barks will play lines in the Ink story sequentially.
  • If the Bark Order is anything else, barks will reset the Ink story before barking, so it will always start from the same entrypoint.

Special Content in Ink Files

Actor Tags

For any given line, to specify the actor (speaker) or conversant (listener), use Actor=actorName and/or Conversant=actorName tags. For example, to make the actor Boromir speak a line to the conversant Elrond:

- One does not simply walk into Mordor. # Actor=Boromir # Conversant=Elrond

You can also tick the integration's Actor Names Precede Lines checkbox to specify that the actor name appears at the beginning of the line, separated by a colon:

- Boromir: One does not simply walk into Mordor. # Conversant=Elrond

External Functions

To make Dialogue System functions available to your Ink story, the Dialogue System integration will automatically register these external functions if you include the definitions below to the top of your Ink file at runtime:

EXTERNAL ShowAlert(x)                 // ShowAlert("message"): Shows an alert message.
EXTERNAL Sequence(x)                  // Sequence("sequence"): Plays sequencer commands in string x. Note: Use [[x]] instead of {{x}} for shortcuts and => instead of -> to send messages.
EXTERNAL CurrentQuestState(x)         // CurrentQuestState("quest"): Returns the current quest state.
EXTERNAL CurrentQuestEntryState(x,y)  // CurrentQuestEntryState("quest", entry#): Returns the current quest entry state.
EXTERNAL SetQuestState(x,y)           // SetQuestState("quest", "inactive|active|success|failure"): Sets a quest state.
EXTERNAL SetQuestEntryState(x,y,z)    // SetQuestEntryState("quest", entry#, "inactive|active|success|failure"): Sets a quest entry state.
EXTERNAL GetBoolVariable(x)           // Returns the bool value of Dialogue System variable x.
EXTERNAL GetIntVariable(x)            // Returns the int value of Dialogue System variable x.
EXTERNAL GetStringVariable(x)         // Returns the string value of Dialogue System variable x.
EXTERNAL SetBoolVariable(x,y)         // Sets Dialogue System variable x to value of bool y.
EXTERNAL SetIntVariable(x,y)          // Sets Dialogue System variable x to value of int y.
EXTERNAL SetStringVariable(x,y)       // Sets Dialogue System variable x to value of string y.
EXTERNAL Lua(x)                       // Runs Lua code x and returns the result as a string.

You may also want to add these fallback functions at the bottom of your file so you can test your story outside of the Dialogue System:

// Fallback functions

== function ShowAlert(x) ==
~ return 1

== function Sequence(x) ==
~ return 1

== function CurrentQuestState(x) ==
~ return "inactive"

== function CurrentQuestEntryState(x,y) ==
~ return "inactive"

== function SetQuestState(x,y) ==
~ return 1

== function SetQuestEntryState(x,y,z) ==
~ return 1

== function GetBoolVariable(x) ==
~ return false

== function GetIntVariable(x) ==
~ return 1

== function GetStringVariable(x) ==
~ return ""

== function SetBoolVariable(x,y) ==
~ return 1

== function SetIntVariable(x,y) ==
~ return 1

== function SetStringVariable(x,y) ==
~ return 1

== function Lua(x) ==
~ return ""

Lua Functions

These functions are available in the Dialogue System's Lua environment:

Function Description Example
SetInkBool("variable", value) Sets a Boolean value in your Ink stories. SetInkBool("teacup", true)
SetInkNumber("variable", value) Sets a number value in your Ink stories. SetInkNumber("wagerAmount", 16000)
SetInkString("variable", "value") Sets a string value in your Ink stories. SetInkString("surname", "Shortshanks")
SetInkList("variable", "value") Sets a string value in your Ink stories. SetInkList("kettleState", "cold")
GetInkBool("variable") Gets a Boolean value from your Ink stories. GetInkBool("teacup")
GetInkNumber("variable") Gets a number value from your Ink stories. GetInkNumber("wagerAmount")
GetInkString("variable") Gets a string value from your Ink stories. GetInkString("surname")
GetInkList("variable") Gets a list value from your Ink stories. GetInkList("kettleState")

Other Methods

DialogueSystemInkIntegration.instance.GetActorsInStory(string storyName, string knot)

This function returns a string[] array of actor names that appear in #Actor=XXX and #Conversant=XXX tags as well as actor names preceding lines (e.g., "Bob: Hi, I'm Bob.") if Actor Names Precede Lines is ticked.

If knot is blank, it processes the entire story.

Notes:

  1. The returned array will not include the default player and NPC, since they are not explicitly named.
  2. This method must process the entire Ink story. It may take some time on large stories.

InkEntrypoint.FromString(string s)

Returns an InkEntrypoint object (containing 3 strings: story, knot, and stitch) from a string of any of these formats:

  • "story"
  • "story/knot"
  • "story/knot.stitch"

The corresponding InkEntrypoint.ToString() method returns the string representation of an InkEntrypoint object.

[InkEntrypoint] Attribute

You can add the [InkEntrypoint] attribute to a public string variable in your scripts to show the variable in the inspector as a dropdown from which you can select stories, knots, and stitches.


<< Import & Export