Text Substitution Reference
DialogueCraft replaces curly-brace patterns in dialogue text with runtime values. This page documents every supported pattern, the resolution order, and practical examples.
When Substitution Happens
Text substitution is performed at runtime by LocalizationManager.SubstituteAll() each time a Text node is displayed. The DialogueRunner calls LocalizationManager.SetDialogueContext() before processing each text node, which sets the current speaker and listener identifiers. The substitution then resolves patterns in the following order:
- Relationship patterns (
{Relationship.A.B.Type}) - Actor field patterns (
{Actor.Name.Field}) - Speaker/Listener field patterns (
{Speaker.Field},{Listener.Field}) - Simple patterns (
{VarName}) -- including built-in names and global/local variables
This ordering matters because more specific patterns (with dots) are matched first, preventing them from being partially consumed by the simpler {word} pattern.
If a pattern cannot be resolved (variable not found, actor not recognized), the original {Pattern} text is left in place unchanged.
Pattern Reference
Global and Local Variables
Syntax: {VariableName}
Resolves against global variables first, then local (dialogue-scoped) variables. The variable name must consist of word characters (letters, digits, underscores).
| Pattern | Resolves To |
|---|---|
{PlayerName} | Value of the global variable PlayerName |
{PlayerGold} | Value of the global variable PlayerGold |
{tempCount} | Value of the local variable tempCount (if no global with that name exists) |
Value formatting: Int values are rendered as-is (42). Float values use two decimal places (3.14). Bool values become true or false. String values are inserted directly.
Example in dialogue:
Welcome back, {PlayerName}! You have {PlayerGold} gold coins.
Actor Fields
Syntax: {Actor.NameOrID.FieldName}
Retrieves a specific character's actor field value. The NameOrID can be either:
- The character's display name with spaces replaced by underscores (e.g.,
Merchant_Doran) - The character's internal ID (e.g.,
merchant_01)
The system attempts to resolve the identifier through the character database, checking both display names and IDs.
| Pattern | Resolves To |
|---|---|
{Actor.Merchant_Doran.Friendship} | Merchant Doran's Friendship field value |
{Actor.merchant_01.TimesVisited} | The character with ID merchant_01's TimesVisited value |
{Actor.Knight.Trust} | The Knight character's Trust field value |
Example in dialogue:
Doran remembers you. His friendship level is {Actor.Merchant_Doran.Friendship}.
Speaker and Listener Names
Syntax: {Speaker}, {Listener}
These resolve to the display name of the current speaker or listener as set by the dialogue context.
| Pattern | Resolves To |
|---|---|
{Speaker} | Display name of the character speaking this line |
{Listener} | Display name of the character being spoken to |
Example in dialogue:
{Speaker} turns to {Listener} and says nothing.
Speaker and Listener Field Values
Syntax: {Speaker.FieldName}, {Listener.FieldName}
Retrieves an actor field value from the current speaker or listener, without needing to know their identity at authoring time. This is useful for shared dialogues or generic lines.
| Pattern | Resolves To |
|---|---|
{Speaker.Friendship} | The current speaker's Friendship field value |
{Listener.Mood} | The current listener's Mood field value |
{Speaker.Title} | The current speaker's Title field value |
Example in dialogue:
[{Speaker.Title}] {Speaker} nods approvingly. Trust level: {Speaker.Trust}.
Speaker and Listener IDs
Syntax: {SpeakerId}, {ListenerId}
These resolve to the internal character ID (not the display name) of the current speaker or listener. Useful for debugging or when your game logic needs to reference characters by ID.
| Pattern | Resolves To |
|---|---|
{SpeakerId} | Internal ID of the current speaker (e.g., merchant_01) |
{ListenerId} | Internal ID of the current listener (e.g., player) |
Relationships
Syntax: {Relationship.FromActor.ToActor.Type}
Retrieves the relationship value between two actors. Relationships are directional -- the value from A to B may differ from B to A. The result is formatted as a whole number (no decimal places).
| Pattern | Resolves To |
|---|---|
{Relationship.player.merchant.Trust} | Player's trust toward the merchant |
{Relationship.merchant.player.Trust} | Merchant's trust toward the player |
{Relationship.player.knight.Respect} | Player's respect toward the knight |
Example in dialogue:
The merchant eyes you cautiously. Trust: {Relationship.player.merchant.Trust}/100.
Complete Example
Consider a dialogue with a merchant character. The player has visited before, and various variables track the relationship:
Variables in play:
- Global:
PlayerName= "Aria",PlayerGold= 250 - Actor (Merchant Doran):
Friendship= 45,TimesVisited= 3,HasDiscount= true - Relationship: player -> merchant_doran Trust = 72
- Local:
itemCount= 2
Dialogue text (as authored):
Ah, {PlayerName}! Welcome back for visit number {Actor.Merchant_Doran.TimesVisited}.
I see you have {PlayerGold} gold. As a friend with {Actor.Merchant_Doran.Friendship}
friendship points and {Relationship.player.merchant_doran.Trust} trust,
I will give you a special price on those {itemCount} items.
Output at runtime:
Ah, Aria! Welcome back for visit number 3.
I see you have 250 gold. As a friend with 45
friendship points and 72 trust,
I will give you a special price on those 2 items.
Using Substitution in Text Nodes
Type patterns directly into the text field of any Text node. No special setup is required -- the DialogueRunner processes all substitution patterns automatically before displaying text to the player.
Patterns can be combined freely and placed anywhere in the text, including within rich text tags:
<color=#FFD700>{Speaker}</color> says: "Your gold: {PlayerGold}"
Substitution from C# Code
You can invoke text substitution manually in your own code:
// Full substitution using the shared variable system
string result = LocalizationManager.SubstituteAll(
"Hello {PlayerName}, trust is {Relationship.player.merchant.Trust}."
);
// Simple named variable substitution (no scope resolution)
string result = LocalizationManager.SubstituteVariables(
"You have {gold} gold and {gems} gems.",
("gold", 100), ("gems", 5)
);
// Substitution from a dictionary
var vars = new Dictionary<string, object>
{
{ "gold", 100 },
{ "gems", 5 }
};
string result = LocalizationManager.SubstituteVariables(
"You have {gold} gold and {gems} gems.", vars
);
// Substitution from a VariableStore directly
string result = LocalizationManager.SubstituteVariables(
"Gold: {PlayerGold}", variableStore
);
SubstituteAll is the method used internally by the dialogue system. It resolves all pattern types (relationships, actors, speaker/listener, globals, locals) using DialogueRunner.SharedVariables and the current dialogue context.
The simpler SubstituteVariables overloads only handle {name} patterns against explicitly provided values -- they do not resolve actor fields, relationships, or speaker/listener context.
Pattern Summary
| Pattern | Example | Description |
|---|---|---|
{VarName} | {PlayerGold} | Global variable, then local variable |
{Actor.Name.Field} | {Actor.Merchant_Doran.Friendship} | Specific actor's field (by display name or ID) |
{Speaker} | -- | Current speaker's display name |
{Listener} | -- | Current listener's display name |
{Speaker.Field} | {Speaker.Friendship} | Current speaker's actor field value |
{Listener.Field} | {Listener.Mood} | Current listener's actor field value |
{SpeakerId} | -- | Current speaker's internal ID |
{ListenerId} | -- | Current listener's internal ID |
{Relationship.A.B.Type} | {Relationship.player.merchant.Trust} | Directional relationship value between two actors |