Skip to main content

Variables & Conditions

Variables let you track game state, control dialogue flow with branching, and personalize text through substitution. DialogueCraft provides a unified variable system with multiple scopes, a visual node for modifications, and a full C# API.


Variable Types

Every variable has one of four types:

TypeUI LabelDescriptionExample Values
IntintWhole numbers0, 42, -5
FloatfloatDecimal numbers0.75, 3.14
BoolboolTrue or falsetrue, false
StringstringText"Hello", "sword"

Types determine which operations and comparison operators are available. When a variable is created at runtime without an explicit type, the system infers the type from the value assigned to it.


Variable Scopes

Global Variables

Global variables persist across all dialogues and play sessions (when saved). They are the primary way to track game-wide state such as quest progress, player stats, or story flags.

Definition: Create and manage global variables in the Variables tab of the Dialogue Editor, or through the VariableDatabase ScriptableObject asset referenced in DialogueCraft Settings.

Examples: PlayerGold, hasMetKnight, mainQuestStage

Persistence: Global variables are included in save data automatically. They survive dialogue endings and scene loads.

Actor Variables

Actor variables are per-character fields. Each character can define its own set of fields (e.g., Friendship, TimesVisited, HasDiscount), and every character maintains independent values.

Definition: Add fields to a character in the Characters tab of the Dialogue Editor. Each field on a CharacterData becomes an actor variable with a name, type, and default value.

Examples: A "Merchant" character might have Friendship (int, default 0), HasDiscount (bool, default false), and TimesVisited (int, default 0).

Initialization: Call DialogueVariables.InitializeActorFieldsFromDatabase(characterDatabase) at game start to populate default values. This only sets values for fields that have not already been set, so it preserves runtime state on subsequent calls.

Local Variables

Local variables are temporary and scoped to a single dialogue. They reset automatically when the dialogue ends.

Definition: Add local variables in the Inspector panel of the Dialogue Editor when a dialogue asset is selected.

Use cases: Tracking how many times a loop has executed, storing a temporary choice result, or counting items within a single conversation.

Relationships

Relationships are directional float values between two actors. The relationship from Actor A to Actor B can differ from B to A.

Examples: Player -> Merchant (Trust: 75) is independent from Merchant -> Player (Trust: 50).

Relationships are set and queried through the DialogueVariables API (see Runtime API below).


Variable Node

The Set Variable node modifies a variable value during dialogue execution. It appears as a purple node in the graph editor.

Configuration

  1. Scope -- Select Global, Actor, or Local.
  2. Actor -- (Actor scope only) Choose which character's field to modify. The dropdown shows cast members first, with an "All Characters..." escape hatch.
  3. Variable -- Pick the variable or actor field to modify. The dropdown is filtered by scope and shows type badges.
  4. Operation -- Choose how to modify the value.
  5. Value -- The operand for the operation. The input field adapts to the variable type (toggle for bool, number field for int/float, text field for string).

Operations

Available operations depend on the variable type:

OperationIntFloatBoolStringDescription
SetYesYesYesYesReplace with the given value
AddYesYes----Add to the current value
SubtractYesYes----Subtract from the current value
MultiplyYesYes----Multiply by the given value
DivideYesYes----Divide by the given value (safe: skips if zero)
Toggle----Yes--Flip true/false (no operand needed)
Append------YesConcatenate text to the end

Conditions

Conditions check variable values to control dialogue flow. They are used in Branch nodes and on individual choices within Choice nodes.

Branch Node

The Branch node (labeled "Condition" in the editor) evaluates one or more condition groups and routes dialogue to the first matching branch. If no conditions match, the Else output is taken.

Each branch can contain multiple conditions combined with AND or OR logic:

  • AND (default): All conditions in the group must pass.
  • OR: Any single condition passing is sufficient. Toggle this with the OR switch that appears when a branch has multiple conditions.

Comparison Operators

OperatorSymbolNeeds ValueApplicable Types
Equals==YesInt, Float, Bool, String
Not Equals!=YesInt, Float, Bool, String
Greater Than>YesInt, Float
Greater Than or Equal>=YesInt, Float
Less Than<YesInt, Float
Less Than or Equal<=YesInt, Float
ContainshasYesString
Starts WithstartsYesString
Ends WithendsYesString
Is Trueis trueNoBool
Is Falseis falseNoBool
Is Setis setNoAll (checks existence/non-empty)
Is Not Setnot setNoAll (checks empty/null)

Note: Float equality uses Mathf.Approximately for safe floating-point comparison.

Variable-to-Variable Comparisons

Conditions can compare a variable against a literal value or against another variable. Click the mode toggle button on a condition row to switch between value mode and variable mode. In variable mode, you select a second variable (from any scope) as the comparison target.

Scope-Aware Evaluation

Conditions support all three variable scopes. When configuring a condition, the dropdown shows global variables, local variables (suffixed with (local)), and actor variables (formatted as CharacterName.FieldName). The system automatically resolves the correct variable store at runtime based on the stored scope and actor ID.

Choice Conditions

Choices in a Choice node support two types of conditions:

  • Show Conditions: If any condition fails, the choice is hidden entirely.
  • Enable Conditions: If any condition fails, the choice is visible but greyed out (disabled). An optional disabledText explains why.

Text Substitution

You can embed variable values directly in dialogue text using curly-brace patterns like {PlayerName} or {Speaker.Friendship}. These are resolved at runtime before the text is displayed.

For a complete reference of all supported patterns, see the Text Substitution Reference.


Runtime API

The DialogueVariables class is the central facade for all variable access. The shared instance is available at DialogueRunner.SharedVariables.

Global Variables

var vars = DialogueRunner.SharedVariables;

// Get and set
int gold = vars.GetGlobal<int>("PlayerGold", 0);
vars.SetGlobal("PlayerGold", gold + 100);

// Check existence
bool exists = vars.HasGlobal("PlayerGold");

// Direct store access
VariableStore globalStore = vars.Global;

Actor Variables

// Convenience methods
int friendship = vars.GetActor<int>("merchant_01", "Friendship", 0);
vars.SetActor("merchant_01", "Friendship", 50);
bool has = vars.HasActor("merchant_01", "Friendship");

// Store access via method or indexer
VariableStore merchantVars = vars.Actor("merchant_01");
VariableStore merchantVars2 = vars["merchant_01"];
merchantVars.SetVariable("Friendship", 75);

// Initialize from character database (call at game start)
vars.InitializeActorFieldsFromDatabase(characterDatabase);

Local Variables

vars.SetLocal("tempCount", 3);
int count = vars.GetLocal<int>("tempCount", 0);
bool exists = vars.HasLocal("tempCount");

// Local variables are cleared automatically when dialogue ends.
// To clear manually:
vars.ClearLocalVariables();

Relationships

// Set a directional relationship
vars.SetRelationship("player", "merchant", "Trust", 75f);

// Get (with default)
float trust = vars.GetRelationship("player", "merchant", "Trust", 0f);

// Increment / Decrement
vars.IncRelationship("player", "merchant", "Trust", 10f);
vars.DecRelationship("player", "merchant", "Trust", 5f);

// Check existence
bool exists = vars.HasRelationship("player", "merchant", "Trust");

Change Events

Subscribe to OnVariableChanged to react when any variable is modified:

vars.OnVariableChanged += (sender, args) =>
{
Debug.Log($"Variable '{args.VariableName}' changed from {args.OldValue} to {args.NewValue}");
if (args.ActorId != null)
Debug.Log($" (Actor: {args.ActorId})");
};

Save and Load

Export all variable state for integration with your own save system:

// Export
DialogueVariablesSaveData saveData = vars.GetSaveData();
// Serialize saveData with JsonUtility, your save system, etc.

// Import (full replace, not merge)
vars.LoadSaveData(saveData);

The DialogueVariablesSaveData class is serializable and contains global variables, actor variables, and relationships. Embed it in your save file alongside other game data.

VariableStore Methods

Each scope (Global, Local, or an Actor store) is a VariableStore with these methods:

MethodSignatureDescription
GetVariableDialogueVariable GetVariable(string name)Get the raw variable object
SetVariablevoid SetVariable(string name, object value, string actorId = null)Set a value (creates if missing)
GetValue<T>T GetValue<T>(string name, T defaultValue = default)Get a typed value with fallback
HasVariablebool HasVariable(string name)Check if a variable exists
RemoveVariablebool RemoveVariable(string name)Remove a variable
Clearvoid Clear()Remove all variables
GetVariableNamesIEnumerable<string> GetVariableNames()List all variable names
ApplyOperationvoid ApplyOperation(string name, VariableOperation op, string operand)Apply Set/Add/Subtract/etc.