Dynamic Story Scripting with the ink Scripting Language - Daniel Cox - E-Book

Dynamic Story Scripting with the ink Scripting Language E-Book

Daniel Cox

0,0
27,59 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

ink is a narrative scripting language designed for use with game engines such as Unity through a plugin that provides an application programming interface (API) to help you to move between the branches of a story and access the values within it.
Hands-On Dynamic Story Scripting with the ink Scripting Language begins by showing you how ink understands stories and how to write some simple branching projects. You'll then move on to advanced usage with looping structures, discovering how to use variables to set up dynamic events in a story and defining simple rules to create complex narratives for use with larger Unity projects. As you advance, you'll learn how the Unity plugin allows access to a running story through its API and explore the ways in which this can be used to move data in and out of an ink story to adapt to different interactions and forms of user input. You'll also work with three specific use cases of ink with Unity by writing a dialogue system and creating quest structures and other branching narrative patterns. Finally, this will help you to find out how ink can be used to generate procedural storytelling patterns for Unity projects using different forms of data input.
By the end of this book, you will be able to move from a simple story to an intricate Unity project using ink to power complex narrative structures.

Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:

EPUB
MOBI

Seitenzahl: 302

Veröffentlichungsjahr: 2021

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Dynamic Story Scripting with the ink Scripting Language

Create dialogue and procedural storytelling systems for Unity projects

Daniel Cox

BIRMINGHAM—MUMBAI

Dynamic Story Scripting with the ink Scripting Language

Copyright © 2021 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

Group Product Manager: Aaron Lazar

Publishing Product Manager: Harshal Gundetty

Senior Editor: Ruvika Rao

Content Development Editor: Urvi Shah

Technical Editor: Maran Fernandes

Copy Editor: Safis Editing

Project Coordinator: Deeksha Thakkar

Proofreader: Safis Editing

Indexer: Manju Arasan

Production Designer: Prashant Ghare

First published: October 2021

Production reference: 1061021

Published by Packt Publishing Ltd.

Livery Place

35 Livery Street

Birmingham

B3 2PB, UK.

ISBN 978-1-80181-932-9

www.packt.com

To the Inkle Discord and the larger ink community for supporting my previous work creating ink tutorials and video guides. To my friends, both local and remote, for being patient with me while I took on this project.

– Daniel Cox

Contributors

About the author

Daniel Cox is a PhD student in Texts and Technology program and a visiting instructor in the Games and Interactive Media department at the University of Central Florida with a decade of experience creating online learning materials across interactive fiction tools such as Twine, Bitsy, and ink. He previously helped create and served as the managing editor of the Twine Cookbook for 4 years. He currently teaches game design as a full-time instructor and volunteers with the Interactive Fiction Technology Foundation.

I want to thank the people who have supported me, especially my friends and my program advisor, Anastasia Salter.

About the reviewer

Johnnemann Nordhagen is an 18-year veteran of the game industry. He has worked as a QA tester, in Sony's Research and Development department, on the BioShock series at 2K Marin, and was cofounder of The Fullbright Company and the sole programmer on Gone Home. He founded Dim Bulb Games and headed the development of Where the Water Tastes Like Wine, released in February of 2018. He lives in Santa Fe, New Mexico.

Table of Contents

Preface

Section 1: ink Language Basics

Chapter 1: Text, Flow, Choices, and Weaves

Technical requirements

Understanding branching narratives as a flow

Nonlinear storytelling

Introducing ink

Text flowing down

The smallest unit is a line

Gluing lines together

Using comments as notes to authors

Creating choices and making weaves

Making weaves

Choices within choices

Selective choice output

Gathering points

Disappearing and sticky choices

Summary

Questions

Chapter 2: Knots, Diverts, and Looping Patterns

Technical requirements

Tangling a flow in knots

Creating knots

Diverting between knots

Using DONE and END

Moving between sections

Knots and stitches

Dividing up a story across different files

Looping knots

Looping structures

Revisiting sticky choices

Detecting and changing options

Labeled and conditional options

Building dynamic weaves

Summary

Questions

Chapter 3: Sequences, Cycles, and Shuffling Text

Technical requirements

Using alternatives

Sequences

Cycles

Shuffles

Creating multi-line alternatives

Multi-line cycles

Multi-line sequences

Nesting alternatives

Combining cycles and shuffles

Shuffling shuffles

Summary

Q&A

Chapter 4: Variables, Lists, and Functions

Technical requirements

Storing values using VAR

Showing variables

Updating variables

Storing the current values of alternatives

Working with LIST

Making a LIST

Updating LIST values

Calling functions

Common mathematics functions

Using LIST functions

Making new functions and calling knots

Summary

Questions

Chapter 5: Tunnels and Threads

Technical requirements

Diverting to a divert

Making tunnels

Tunneling to tunnels

Pulling on threads

Making threads

Using multiple threads

Ending threads

Combining tunnels and threads

Reusing tunnels and repeating threads

Threads with tunnels

Summary

Questions

Section 2: ink Unity API

Chapter 6: Adding and Working with the ink-Unity Integration Plugin

Technical requirements

Adding the ink-Unity Integration plugin

Finding and importing the plugin

Verifying the package is installed

Working with ink files

Adding ink source files

Editing source files with Inky

Updating ink source files

Adjusting plugin settings

Finding ink-Unity Integration settings

Updating automatic re-compilation

Summary

Questions

Chapter 7: Unity API – Making Choices and Story Progression

Technical requirements

Loading a compiled ink story

Creating a script component

Adding the ink Story API

Running an ink JSON file

Checking whether a story can continue

Selecting options programmatically

Detecting ink choices

Making choices using the Unity API

Loading all text until the next weave

Creating a dynamic user interface

Creating a new project and game objects

Associating Prefab and ink JSON files

Making a dynamic user interface

Summary

Questions

Chapter 8: Story API – Accessing ink Variables and Functions

Technical requirements

Changing ink variables outside a story

Accessing ink variables

Changing the value of the ink variables

Calling ink functions externally

Verifying and evaluating ink functions

Retrieving the ink function text output

Controlling a story through variables and functions

Preparing a user interface

Scripting user interface objects

Adjusting the presentation values

Summary

Questions

Chapter 9: Story API – Observing and Reacting to Story Events

Technical requirements

Listening for variable changes

Dynamically responding to ink stories

Observing multiple ink values

Summary

Questions

Section 3: Narrative Scripting with ink

Chapter 10: Dialogue Systems with ink

Technical requirements

Writing dialogue in Ink using tags

Tagging ink text

Using speech tags

Reviewing approaches to tagging dialogue

Dialogue loops and story knots

Click to continue

Counting choices for trees

User interface models for conversations

Listing dialogue options

Presenting a radial menu for dialogue

Summary

Questions

Chapter 11: Quest Tracking and Branching Narratives

Technical requirements

Making a quest count

Creating a quest template in ink

Choosing specific knots in Unity

Tracking progress across multiple quests

Building on the ink quest template

Making Quest and Dialogue classes in Unity

Organizing multiple quest files

Toggling quests

Displaying and awarding player progression

Tracking quest values

Showing player progress

Summary

Q&A

Chapter 12: Procedural Storytelling with ink

Technical requirements

Introducing procedural storytelling in ink

Random encounters

Weighted randomness

Conditional content

Loading values into ink

Substitution grammars

Story planning

Coding collections in Unity

Using multiple stories

Conditionally choosing stories

Summary

Questions

Assessments

Other Books You May Enjoy

Section 1: ink Language Basics

By the time you've completed this section, you will be able to describe the major core language concepts and patterns of ink and how to use their syntax. This section contains the following chapters:

Chapter 1, Text, Flow, Choices, and WeavesChapter 2, Knots, Diverts, and Looping PatternsChapter 3, Sequences, Cycles, and Shuffling TextChapter 4, Variables, Lists, and FunctionsChapter 5, Tunnels and Threads

Chapter 1: Text, Flow, Choices, and Weaves

This chapter introduces the core concepts of nonlinear storytelling by examining branching narratives and how ink supports creating them. Building on these concepts, this chapter also reviews using lines, text within them, and how to combine them.

As a central element of creating nonlinear, interactive narratives in ink, choices are explained and how best to use them. Weaves and collections of choices are discussed within the context of when a large branching structure might be needed and how to collapse these weaves into simpler parts using gathering points.

In this chapter, we will cover the following main topics:

Understanding branching narratives as a flowCreating choices and making weavesDisappearing and sticky choices

Technical requirements

The examples used in this chapter, in *.ink files, can be found online on GitHub: https://github.com/PacktPublishing/Dynamic-Story-Scripting-with-the-ink-Scripting-Language/tree/main/Chapter1.

Understanding branching narratives as a flow

When holding a physical book, a reader moves through a story by turning its pages. The movement between pages is also a movement through the story. What is experienced by the reader is called a narrative. The story is the packaging of its content into different parts called pages. The reader's narrative, however, is the experience of the story across those pages.

In a digital setting, there are no physical pages. The words of a story could be stored as part of a simple text file or bundled together in something more complex. Parts of a digital story, which are the pages in a physical book, can also be arranged much more easily, and the reader might experience them in different configurations, creating new narratives from the same story content.

Consider the following example, where each sentence is a part of a story:

The sun was shining in a clear blue sky.

Clouds rolled in and it began to rain.

The clouds cleared away and the sun emerged.

When taken in order from the first sentence to the last one, there is a story where the major parts are the sun shining, the clouds coming in, but then the clouds leaving and the sun shining again. However, what happens if the parts are rearranged?

Example 1:

The clouds cleared away and the sun emerged.

The sun was shining in a clear blue sky.

Clouds rolled in and it began to rain.

With a different ordering, a new narrative is created for the reader. In this version, the progression begins with the sun emerging and shining. Next, the clouds move in and it begins to rain. In either case, only three events are used, but their order affects the narrative experience of the reader.

Nonlinear storytelling

In the second example, the story still makes sense. This time, however, the events start with the clouds, move into the sun shining, and end with the clouds returning. The second example, in moving around the events, is an example of nonlinear storytelling, where the events or parts of a story are experienced in a new or different way than created or originally written. The progression is not linear from one part to another as created in the story, but a cohesive narrative is still created:

Figure 1.1 – Mapping nonlinear storytelling

The structures created by navigating a nonlinear story are often compared to trees. They start with a trunk and then, as different parts are encountered over others, a branching pattern is created, with each branch representing a movement through parts of a story from one end to another. The narrative traversal through a nonlinear story creates a branching narrative, where different parts were or were not encountered. The map of the experienced narrative represents a particular branch of the overall tree of the story and its parts.

While nonlinear storytelling can be done with a printed book, it is often much more difficult. In a digital setting, where events can be broken up into different parts, rearranging them can often be as easy as selecting them and dragging them to a different part of the same document. This consequence of representing stories as data makes writing code to handle arranging the different parts easier too. This is known as narrative scripting.

Introducing ink

ink is a narrative scripting language. It determines which part of the story comes next for the reader. As a user clicks or presses buttons, the code written in ink makes the decision between which branches they should visit and when. Based on rules written by an author, the code can even repeat the same part of the story with new values.

Because ink is designed for the purpose of scripting narratives, it understands navigation through a story as a special concept called flow. As the reader moves through the different parts, they are creating their own experienced narrative, which ink calls the flow. In fact, one of the most common errors encountered by authors is where the flow runs out of a story. Even when writing a nonlinear story with different branches, the story must start and end somewhere. Even if all the parts between the start and end of a narrative change each time a user traverses the parts of a story, these two points define the range of possible branches.

Text flowing down

The concept of flow also extends to how code is understood in ink. All movement across a story in ink moves down from the top of the code to the bottom unless told to navigate to a different part in the story.

The example stories shared earlier in this chapter are both also code examples. ink is designed to create branching narratives and supplies the ability to write code to create these structures. This means text or words written in a story without any other special characters or syntax are valid in ink.

Spacing within a line of text is important in ink. Because the text is considered a form of code, ink assumes any use of spacing is a deliberate choice on the part of the author. For example, adding extra spaces between words is not removed in its output:

The sun was        shining in a clear blue sky.

Output:

The sun was        shining in a clear blue sky.

ink ignores any empty lines. It assumes each line of text is important and any spacing between them should be ignored as something unimportant to the story itself.

Example 2:

The sun was shining in a clear blue sky.

Clouds rolled in and it began to rain.

The clouds cleared away and the sun emerged.

Output:

The sun was shining in a clear blue sky.

Clouds rolled in and it began to rain.

The clouds cleared away and the sun emerged.

The smallest unit is a line

The use of three lines as part of a story when introducing nonlinear storytelling was not a mistake. The smallest unit within an ink story is a single line:

This is a story.

Because ink considers text to be a part of the code, a single line with only four words is a completely valid story. Adding more lines would also extend what would be presented to the reader, but a single line can be a story by itself:

This is a story in ink.

It has two lines.

The use of the term line is important in ink. When reading a physical book, the smallest unit in a story is usually a sentence. This is often the smallest complete thought in a larger work. In a digital context, and specifically within ink, a line is the smallest unit. When ink loads a story, it moves through the story line by line. It treats each as equally important as the last.

As more complex code is introduced, the concept of a line will become more important as well. However, just like the single-line example, a story need not be complex to be important. To ink, a story is composed of lines. This could be one or potentially many more.

Gluing lines together

An author may need to use multiple lines of text as one "line" of code. For these situations, ink provides a concept called glue. When the less-than and greater-than symbols, <>, are used together, they glue the content of one onto the next, creating one long line:

Example 3:

This <>

is <>

considered <>

one <>

line of text.

Output:

This is considered one line of text.

Spacing when using glue is important. As with spacing within a single line, ink respects the choices of the author when presenting text in a single line. When using glue, these spaces are also respected.

Without the spaces after each word, the use of glue in the previous example would glue all the words together:

This<>

is<>

considered<>

one<>

line of text.

Output:

Thisisconsideredoneline of text.

Using comments as notes to authors

As a scripting language, ink also provides the ability to include notes within the code of a story. Borrowing from a more general programming term, ink calls these notes comments. They begin with two slashes and then contain the content of the comment. Any part of the line is also considered part of the comment:

Example 4:

The sun was shining in a clear blue sky.

// Change this next line in the future.

Clouds rolled in and it began to rain.

// Maybe update this story in a future version?

The clouds cleared away and the sun emerged.

When run, the text of the story would be treated as its code. However, any use of comments would not appear in the output of the story. Comments are only designed for human audiences and allow an author to explain the code to other audiences, or, more generally, as notes to themselves or other members of their team about how something works.

Working with Inky

To help authors more quickly develop a story in ink, Inkle Studios has created a program called Inky. This editing tool allows an author to write code and see it run as a preview of its output:

Figure 1.2 – Screenshot of the Inky editor

While initially developed by Inkle Studios, Inky is now an open source project and often sees dozens of commits by the community to fix small issues or add new functionality. A new minor version usually comes out every year.

At the time of writing, Inky does not have a Windows installer but provides builds for macOS X and Linux systems. When running on Windows or Linux, the ZIP file needs to be unzipped to an existing folder and the Inky.exe (for Windows) or Inky (for Linux) file run to open the editor.

Using Inky

Inky presents an interface with two panes:

The left is where ink code is written.The right shows a preview of the code while it is being developed.

This allows users to quickly see how their code would produce different outputs depending on what code was used.

Inky's most useful function is the ability to "rewind" a story to an earlier point and try a different branch of the narrative. This allows authors to test branches of their story more quickly, without needing to restart the story each time.

Figure 1.3 – The "Rewind a single choice" and "Restart story" buttons

Important note

This book will use screenshots from Inky to show the resulting output of different code.

Creating choices and making weaves

While having code pick parts of a story to produce a new possible narrative for a user could be exciting, most users want some input on what happens next. They want an interactive story. In ink, interactivity is created by presenting the user with choices. Depending on which choice the reader makes, the narrative could then branch in different ways.

Making weaves

Choices in ink are a part of another important concept, weaves. As a user creates a flow from one part to another, they often encounter intersections within a story where branches might be possible depending on what choice is made. This is what is known as a weave within ink. These are collections of choices where each one has the potential to branch the story in different ways.

Choices are written in ink using an asterisk, *. What might appear as a list of things is, in ink, each a different choice within a single weave:

What did I want to eat?

* Apples

* Oranges

* Pears

In the previous code, each line starting with an asterisk is a choice. It starts from the asterisk and extends to the end of the line. Everything that is part of the line becomes a part of the choice. Each asterisk on a new line creates a new choice within the weave:

We smiled again at each other across the coffee shop. I had seen her coming in at this same time for over a week now. We had spoken a couple of times, but I could not bring myself to talk to her more.

As I looked back down at my coffee, I needed to decide.

* I decided to go talk to her.

"Uh. Hi!" I said, maybe a little too loud as I approached her.

* I gave up for now. Maybe tomorrow.

I shook my head to myself and looked away from her and out the window. Today was not the day.

Each choice in a weave has the potential to branch the narrative. In the previous code, there are two choices. However, after each choice is another line of code. When run, ink would understand each line following a choice as being the result of choosing the reader. To help to visually differentiate the result of the choice better, the line following a choice is often indented at its start.

Changing the previous code to use indentation would look as follows:

Example 6:

We smiled at each other again across the coffee shop. I had seen her coming in at this same time for over a week now. We had spoken a couple of times, but I could not bring myself to talk to her more.

As I looked back down at my coffee, I needed to decide.

* I decided to go talk to her.

    "Uh. Hi!" I said, maybe a little too loud, as I approached       her.

* I gave up for now. Maybe tomorrow.

    I shook my head to myself and looked away from her and out       the window. Today was not the day.

Choices within choices

Choices can also appear inside other choices. These are sub-choices and use an additional asterisk to indicate that they are the result of a previous layer of a weave:

Example 7:

Should I really forgive her again? I thought about the options in front of me as I considered what she told me.

* I forgive her.

    ** She does the same behavior again.

        I just end up hurt again.

    ** She really does change.

        She does not have another affair and maybe we can save           our relationship.

* I do not forgive her.

    ** I would have to move out.

        I would need to find another apartment.

    ** I stay with her and try to live again without being in a          relationship.

        I could try going back to being friends like we were           before our relationship.

In the previous code, there are two choices that each lead to their own choices, branching off the central set. This is an example of a complex weave. The first layer of the weave is the initial two choices. The result of either choice is then another weave, which then ends in text. Depending on the user's flow, they might only see part of the overall story when moving between these parts.

One possible branch within the complex weave could be the following output for the reader:

Output

Should I really forgive her again? I thought about the options in front of me as I considered what she told me.

I forgive her.

She does the same behavior again.

I just end up hurt again.

A different series of branches within the story might also create the following output:

Should I really forgive her again? I thought about the options in front of me as I considered what she told me.

I do not forgive her.

I would have to move out.

I would need to find another apartment.

Selective choice output

When using choices, the text of the choice itself appears in its output. This can be changed by using a special concept with choices called selective output. By using open and closing square brackets around any text in the line of the choice, it will not appear as part of the output as a result of making the choice:

What did I want to eat?

* [Apples]

* [Oranges]

* [Pears]

I got some food.

In the previous code, the output, regardless of the choice made by the reader, would be the same:

What did I want to eat?

I got some food.

In the cases where the text of the choice is different from what is shown to the reader, the term option is used. A choice is created in ink using code. What is ultimately shown to the reader is an option.

In more advanced code examples, ink can generate choices dynamically. In these cases, as with selective output, it can be important to understand the use of a choice as something written by a developer and an option as selected by the reader. Often, these can be the same thing, but they do not have to be when writing code in ink.

Selective output also allows creating more dynamic output by selectively showing text from an option in the output. An effect of using selective output is that the closing square bracket in a line signals an end to what is shown to the reader. Any additional text on the same line is ignored:

Example 8:

I looked at the timer again and then at the wires in front of me. I had five seconds to stop this bomb from exploding.

* [I cut the wire.] It was the green one.

* [I cut the wire.] It was the red one.

* [I cut the wire.] It was the blue one.

Possible output:

I looked at the timer again and then at the wires in front me. I had five seconds to stop this bomb from exploding.

It was the green one.

From the reader's perspective, the previous code would show three options. Each one would read I cut the wire. However, the use of selective output is telling ink to ignore the additional text of each color. After making a choice, the user would then see the result of the choice as a new line, with the use of square brackets excluding anything they enclose.

Selective output can often be useful to hide additional information behind a choice where the reader must pick an option and then see the additional text of a line.

Gathering points

Each choice in a weave can potentially branch a narrative. However, sometimes there is a need to gather one or more branches back to where they began. Instead of leading off in a new direction, a gathering point can be used to collapse a more complex weave into a central point. In ink, gathering points are created using a single minus sign (-) on a line:

You peer down at the desk with two drawers.

* Try to open the top drawer.

    It does not open.

    ** Try again more forcefully.

    ** Give up for now

* Try to open the side drawer.

    It does not open.

    ** Try again more forcefully.

    ** Give up for now

- All the drawers seem locked tight.

In the previous code, there are two choices with two sub-choices each. However, at the bottom of the weave is a gathering point. No matter what branch is taken across the first weave and then into the next layer, the flow will always gather at the last line. This is the power of gathering points: they allow a complex weave with multiple layers to collapse into a single point.

The placement of gathering points is important. In ink, stories flow down from the top to the bottom. If the gathering point appeared before the weave, it would be ignored. Without anything to gather, the gathering point does nothing. This also only affects weaves. Multiple gathering points in a story would do nothing without a weave above them to act as a point of collapsing them.

Gathering points only work on a single weave at a time. As the last line of a weave, they act to gather the choices. However, they only apply to one branching structure at a time. A new gathering point is needed per weave to collapse those branches back together:

Example 9:

You peer down at the desk with two drawers to open.

* [Try the top drawer.]

* [Try the side drawer.]

- All the drawers seem locked tight.

You give up on the drawers and look at the top of the desk.

* [Look at the papers on top of the desk.]

* [Pick up the papers and look through them.]

- You find nothing of interest.

In the previous code, both selective output and gathering points are used to create the illusion of two weaves with two choices each. The outcome of each, because they are using gathering points, is the last line of each. Options are presented to the reader, but the code itself collapses any possible branching of each weave and flows the story from the first weave to the second layer.

Disappearing and sticky choices

The default behavior of a weave is to direct the flow of a story along with one of the branches presented by its choices. When the reader makes a choice, the others disappear, and the branch chosen becomes the current flow of the story. Even when rewinding when using Inky to test a story, there appears to only be one valid branch of a weave at any one time.

Anticipating situations where the reader might revisit a part of a story with choices the reader might not have seen before, ink uses the concept of sticky choices to present the same choices again to the reader. Using sticky choices, each remains open during a revisit and can be used again in the future:

You look at the boulder in front of you.

+ Push the boulder.

Sticky choices are created using the plus sign (+