Custom Dialogue Presenters
Learn how to create Dialogue Presenters that are designed for the specific needs of your game.
The Line Presenter and Options Presenter are handy for many situations. But your game might need to show lines and options in a particular way. When that's the case, you can write your own custom Dialogue Presenter. This gives you full control over how lines and options appear.
Creating a Dialogue Presenter
To make a Dialogue Presenter, you first create a subclass of the DialoguePresenterBase
class. Then, you add this subclass as a component to a game object in your scene. After that, you can add this game object to the Dialogue Presenters list on your scene's Dialogue Runner.
Presenting Lines and Options
By itself, an empty subclass of DialoguePresenterBase
won't do much. You need to implement specific methods to make it show lines and options.
To get how custom Dialogue Presenters work, it helps to understand how the Dialogue Runner handles content. Yarn Spinner scripts use three types of content: lines, options, and commands. Only the first two, lines and options, need to be shown directly to the player.
When the Dialogue Runner finds lines or options, it first figures out the exact content the player needs to see. Once it has this, it sends the content to each of its Dialogue Presenters.
Your scene can have several Dialogue Presenters. And they can all do different things. For instance, you might have one Dialogue Presenter for lines, another for options, and a third for playing voice-over audio.
Getting Localised Content
In compiled Yarn Spinner Scripts, Lines and Options are represented by line IDs. A line ID is a unique code for the text of a line or an option. When Yarn Spinner needs to show a line or option, it asks its Line Provider for a LocalizedLine
object. This object holds the text for the line or option in the player's current language.
If you're showing a group of options, each option in that group has its own LocalizedLine
.
Once a LocalizedLine
is ready, the Dialogue Runner has everything it needs to show content. What happens next depends on whether it's showing a line or an option.
Presenting Lines
When Yarn Spinner comes across a line of dialogue, it calls the RunLineAsync
method on every Dialogue Presenter. This method gets two things: first, the LocalizedLine
from the Line Provider, and second, a LineCancellationToken
. The Dialogue Presenter uses this token to know the line's status. Specifically, it checks if the player wants to speed up the line's display or move to the next line.
In Dialogue Presenters, a line is considered "presented" when the player has seen the whole line and is ready for the next one. What this means in practice varies. For example, a Dialogue Presenter playing voice-over audio might finish when all the audio has played. Another one that shows text gradually might finish when all text is visible and the UI has faded out.
The Dialogue Runner waits until all Dialogue Presenters say they've finished showing the line. Then, it moves to the next bit of dialogue.
The RunLineAsync
method is asynchronous. This means a Dialogue Presenter signals it's done and ready for the next line by returning from the method.
If your game needs to pause dialogue until the player does something (like press a button), your Dialogue Presenter can do this. It simply doesn't return from the RunLineAsync
method until the line cancellation token signals to advance. Because the Dialogue Runner waits for all presenters, the dialogue will pause until your presenter says to go on.
Hurrying and Advancing Lines
Line presentation usually isn't instant. It typically happens over a short period. So, players might want to speed this up or skip it entirely. Dialogue Presenters need to be ready for the player to ask for a line to hurry up or be skipped at any moment during presentation.
The line's state is held in the LineCancellationToken
given during the RunLineAsync
method. This token wraps two other Cancellation Tokens: one for advancing to the next line, and one for making the current line hurry. These tokens are linked. So, if the "next line" token is flagged, the "hurry up" token will be too. But it doesn't work the other way around.
Most times, you won't need to access these tokens directly. You can check the line's status using handy properties. IsHurryUpRequested
on the token tells your custom Dialogue Presenter if the player wants the display to go faster. And IsNextLineRequested
tells you if your Dialogue Presenter should skip the current line completely.
Any part of line presentation that isn't instant should use these properties. This helps decide if they should speed up or be skipped. The same LineCancellationToken
is shared by all Dialogue Presenters. So, if the line's status changes, all presenters see it at the same time. Each Dialogue Presenter decides what "hurrying up" means for it; it's a signal to finish the presentation quickly.
For example, a voice-over presenter might fade out audio quickly or cut it off. A text-revealing presenter might show all remaining text at once or very rapidly. Advancing a line is a more direct signal that the player wants the dialogue to move on. You shouldn't ignore IsNextLineRequested
when it's true. Presenters should clean up and finish showing the line as soon as possible if the player has asked to advance.
You can change the LineCancellationToken
's state using the Dialogue Runner. It has two methods for this. RequestHurryUpLine
sets the token so IsHurryUpRequested
becomes true. RequestNextLine
sets the IsNextLineRequested
flag to true. Since the LineCancellationToken
wraps two linked tokens, these methods also cancel those internal tokens. Requesting the next line also means requesting the line to hurry up. You can safely request a line advance or hurry up multiple times; it won't cause any issues.
Presenting Options
Options are a bit different from lines. They need some kind of player input before the dialogue can go on. The Dialogue Runner needs to know which option was picked.
To manage options, Dialogue Presenters implement the RunOptionsAsync
method. This method gets an array of DialogueOption
objects and a cancellation token. Each DialogueOption
object is an option that can be shown to the player.
When this method is called, the Dialogue Presenter uses the info in the DialogueOption
objects to show choices to the player. Then it waits for player input. Once it knows which option was selected, the method should return that chosen option. The Dialogue Runner then uses this to make the selection.
If your presenter doesn't need to handle options, it can return a null value instead.
The Dialogue Runner will ignore any nulls it gets back from presenters here. The first non-null DialogueOption
it receives is treated as the selected one.
When the Dialogue Runner sends options to its Dialogue Presenters, it expects only one of them to return a non-null option. If none of them return an option, the Dialogue Runner will never know what was picked. And it will wait forever, and ever, and ever.
If more than one presenter returns an option, the Dialogue Runner uses the first one it gets and ignores the others. After getting a non-null option, the Dialogue Runner cancels the cancellation token given in the method. This tells any presenters that haven't returned yet that an option has been selected. So, they can stop waiting for a selection.
Accessing Line Metadata
To get the tags on a line, you use the Metadata
property on the LocalizedLine
objects you receive. Your code decides what to do with these tags.
Last updated
Was this helpful?