Skip to main content
The Dialogue Manager provides a comprehensive C# wrapper that allows seamless integration with C# projects. This wrapper provides type-safe access to all core functionality.

Namespace

using DialogueManagerRuntime;
All C# classes and types are contained within the DialogueManagerRuntime namespace.

DialogueManager Class

The main static class for interacting with the Dialogue Manager from C#.

Properties

GameStates
Godot.Collections.Array
Array of additional game state objects to search for properties and methods during dialogue execution.
DialogueManager.GameStates = new Godot.Collections.Array { myStateObject };
IncludeSingletons
bool
Whether to include autoload singletons when searching for state properties and methods.
DialogueManager.IncludeSingletons = true;
IncludeClasses
bool
Whether to include C# static classes when searching for state properties and methods.
DialogueManager.IncludeClasses = true;
TranslationSource
TranslationSource
The source to use for translations. Options: None, Guess, CSV, PO.
DialogueManager.TranslationSource = TranslationSource.CSV;
GetCurrentScene
Func<Node>
Delegate that returns the current scene node for state resolution.
DialogueManager.GetCurrentScene = () => GetTree().CurrentScene;

Core Methods

ShowExampleDialogueBalloon

Display dialogue using the built-in example balloon.
public static CanvasLayer ShowExampleDialogueBalloon(
    Resource dialogueResource, 
    string key = "", 
    Array<Variant>? extraGameStates = null
)
dialogueResource
Resource
required
The dialogue resource to display
key
string
default:""
The title/label to start from
extraGameStates
Array<Variant>
Additional objects to search for state properties
var dialogue = GD.Load<Resource>("res://example.dialogue");
var balloon = DialogueManager.ShowExampleDialogueBalloon(dialogue, "start");

ShowDialogueBalloon

Display dialogue using your configured custom balloon.
public static Node ShowDialogueBalloon(
    Resource dialogueResource, 
    string key = "", 
    Array<Variant>? extraGameStates = null
)
dialogueResource
Resource
required
The dialogue resource to display
key
string
default:""
The title/label to start from
extraGameStates
Array<Variant>
Additional objects to search for state properties
var dialogue = GD.Load<Resource>("res://example.dialogue");
var balloon = DialogueManager.ShowDialogueBalloon(dialogue, "start");

ShowDialogueBalloonScene

Display dialogue using a specific balloon scene.
public static Node ShowDialogueBalloonScene(
    string balloonScene, 
    Resource dialogueResource, 
    string key = "", 
    Array<Variant>? extraGameStates = null
)
Overloads also accept PackedScene or Node as the first parameter.
balloonScene
string | PackedScene | Node
required
Path to balloon scene, packed scene, or instantiated balloon node
dialogueResource
Resource
required
The dialogue resource to display
key
string
default:""
The title/label to start from
extraGameStates
Array<Variant>
Additional objects to search for state properties
// Using path
var balloon = DialogueManager.ShowDialogueBalloonScene(
    "res://balloons/custom_balloon.tscn",
    dialogue,
    "start"
);

// Using PackedScene
var scene = GD.Load<PackedScene>("res://balloons/custom_balloon.tscn");
var balloon = DialogueManager.ShowDialogueBalloonScene(scene, dialogue, "start");

// Using instantiated Node
var balloonNode = myBalloonScene.Instantiate();
var balloon = DialogueManager.ShowDialogueBalloonScene(balloonNode, dialogue, "start");

GetNextDialogueLine

Manually retrieve the next line of dialogue.
public static async Task<DialogueLine?> GetNextDialogueLine(
    Resource dialogueResource, 
    string key = "", 
    Array<Variant>? extraGameStates = null, 
    MutationBehaviour mutation_behaviour = MutationBehaviour.Wait
)
dialogueResource
Resource
required
The dialogue resource to traverse
key
string
default:""
The title/label to start from (or continue from using the line’s NextId)
extraGameStates
Array<Variant>
Additional objects to search for state properties
mutation_behaviour
MutationBehaviour
default:"Wait"
How to handle mutations: Wait (default), DoNotWait, or Skip
var dialogue = GD.Load<Resource>("res://example.dialogue");
var line = await DialogueManager.GetNextDialogueLine(dialogue, "start");

if (line != null)
{
    GD.Print($"{line.Character}: {line.Text}");
    
    // Get next line
    var nextLine = await DialogueManager.GetNextDialogueLine(dialogue, line.NextId);
}
Returns null when the dialogue ends.

GetLine

Retrieve a single line without advancing dialogue state.
public static async Task<DialogueLine?> GetLine(
    Resource dialogueResource, 
    string key = "", 
    Array<Variant>? extraGameStates = null
)
dialogueResource
Resource
required
The dialogue resource
key
string
default:""
The title/label of the line to retrieve
extraGameStates
Array<Variant>
Additional objects to search for state properties
var line = await DialogueManager.GetLine(dialogue, "greeting");
GD.Print(line?.Text);

CreateResourceFromText

Generate a dialogue resource from a string at runtime.
public static Resource CreateResourceFromText(string text)
text
string
required
Dialogue script text to parse
var resource = DialogueManager.CreateResourceFromText(
    "~ greeting\nNathan: Hello, world!"
);
var balloon = DialogueManager.ShowExampleDialogueBalloon(resource, "greeting");
This method will throw an error if there are syntax errors in the dialogue text. A balloon or dialogue must be opened for the dialogue to attach to.

Mutate

Execute a mutation dictionary against game state.
public static async void Mutate(
    Dictionary mutation, 
    Array<Variant>? extraGameStates = null, 
    bool isInlineMutation = false
)
mutation
Dictionary
required
The mutation to execute
extraGameStates
Array<Variant>
Additional objects to search for state properties
isInlineMutation
bool
default:"false"
Whether this is an inline mutation
var mutation = new Dictionary
{
    { "expression", "player_health = 100" }
};
await DialogueManager.Mutate(mutation);

Translation Methods

StaticIdToLineIds

Convert a static translation ID to an array of line IDs.
public static Array<string> StaticIdToLineIds(
    Resource dialogueResource, 
    string staticId
)
var lineIds = DialogueManager.StaticIdToLineIds(dialogue, "greeting_001");

StaticIdToLineId

Convert a static translation ID to a single line ID.
public static string StaticIdToLineId(
    Resource dialogueResource, 
    string staticId
)
var lineId = DialogueManager.StaticIdToLineId(dialogue, "greeting_001");

Utility Methods

GetErrorMessage

Get a human-readable error message for an error code.
public static string GetErrorMessage(int error)
var errorMsg = DialogueManager.GetErrorMessage(Error.FileNotFound);
GD.PrintErr(errorMsg);

Event Handlers

The C# wrapper provides strongly-typed event handlers for all Dialogue Manager signals.

DialogueStarted

Emitted when dialogue begins.
public static event DialogueStartedEventHandler? DialogueStarted;
// Delegate: void DialogueStartedEventHandler(Resource dialogueResource)
DialogueManager.DialogueStarted += (Resource dialogueResource) =>
{
    GD.Print("Dialogue started!");
};

DialogueEnded

Emitted when dialogue finishes.
public static event DialogueEndedEventHandler? DialogueEnded;
// Delegate: void DialogueEndedEventHandler(Resource dialogueResource)
DialogueManager.DialogueEnded += (Resource dialogueResource) =>
{
    GD.Print("Dialogue ended!");
};

PassedLabel

Emitted when dialogue passes a title/label.
public static event PassedLabelEventHandler? PassedLabel;
// Delegate: void PassedLabelEventHandler(string label)
DialogueManager.PassedLabel += (string label) =>
{
    GD.Print($"Passed label: {label}");
};

GotDialogue

Emitted when a new dialogue line is retrieved.
public static event GotDialogueEventHandler? GotDialogue;
// Delegate: void GotDialogueEventHandler(DialogueLine line)
DialogueManager.GotDialogue += (DialogueLine line) =>
{
    GD.Print($"{line.Character}: {line.Text}");
};

Mutated

Emitted when a mutation is executed.
public static event MutatedEventHandler? Mutated;
// Delegate: void MutatedEventHandler(Dictionary mutation)
DialogueManager.Mutated += (Dictionary mutation) =>
{
    GD.Print($"Mutation executed: {mutation}");
};

DialogueLine Class

Represents a single line of dialogue with all associated data.

Properties

Id
string
Unique identifier for this line
Type
string
Line type: "dialogue" or "mutation"
NextId
string
ID of the next line to display
Character
string
Name of the speaking character
Text
string
The dialogue text (with BB code)
TranslationKey
string
Translation key for localization
Responses
Array<DialogueResponse>
Array of available response options
Time
string?
Timing information for the line
Speeds
Dictionary
Text speed modifications
InlineMutations
Array<Array>
Inline mutations within the dialogue text
ConcurrentLines
Array<DialogueLine>
Lines that should display simultaneously
ExtraGameStates
Array<Variant>
Additional game state objects for this line
Tags
Array<string>
Tags associated with this line

Methods

HasTag

Check if a tag exists on this line.
public bool HasTag(string tagName)
if (line.HasTag("angry"))
{
    // Play angry animation
}

GetTagValue

Get the value of a tag.
public string GetTagValue(string tagName)
var emotion = line.GetTagValue("emotion");
// For tag "emotion=happy", returns "happy"

Example Usage

var dialogue = GD.Load<Resource>("res://conversation.dialogue");
var line = await DialogueManager.GetNextDialogueLine(dialogue, "start");

while (line != null)
{
    GD.Print($"{line.Character}: {line.Text}");
    
    if (line.HasTag("emotion"))
    {
        var emotion = line.GetTagValue("emotion");
        GD.Print($"Emotion: {emotion}");
    }
    
    if (line.Responses.Count > 0)
    {
        // Handle responses
        foreach (var response in line.Responses)
        {
            if (response.IsAllowed)
            {
                GD.Print($"- {response.Text}");
            }
        }
        break;
    }
    
    line = await DialogueManager.GetNextDialogueLine(dialogue, line.NextId);
}

DialogueResponse Class

Represents a response option in dialogue.

Properties

NextId
string
ID of the line to jump to if this response is selected
IsAllowed
bool
Whether this response is available based on conditions
ConditionAsText
string
The condition expression as text
Text
string
The response text
TranslationKey
string
Translation key for localization
Tags
Array<string>
Tags associated with this response

Methods

GetTagValue

Get the value of a tag on this response.
public string GetTagValue(string tagName)
var priority = response.GetTagValue("priority");

Example Usage

// Connecting to response selection
responsesMenu.Connect("response_selected", Callable.From((DialogueResponse response) =>
{
    GD.Print($"Selected: {response.Text}");
    
    // Continue dialogue from the response's next ID
    var nextLine = await DialogueManager.GetNextDialogueLine(dialogue, response.NextId);
}));

Enums

MutationBehaviour

Controls how mutations are handled during dialogue execution.
public enum MutationBehaviour
{
    Wait,        // Wait for mutation to complete
    DoNotWait,   // Continue immediately without waiting
    Skip         // Skip the mutation entirely
}
var line = await DialogueManager.GetNextDialogueLine(
    dialogue, 
    "start", 
    null, 
    MutationBehaviour.DoNotWait
);

TranslationSource

Specifies the source for dialogue translations.
public enum TranslationSource
{
    None,   // No translation
    Guess,  // Auto-detect from project settings
    CSV,    // Use CSV translation files
    PO      // Use PO translation files
}
DialogueManager.TranslationSource = TranslationSource.CSV;

State Management

When resolving state properties and methods, the Dialogue Manager searches in the following order:
  1. Extra Game States - Objects passed in extraGameStates parameter
  2. Current Scene - The scene returned from GetTree().CurrentScene
  3. Autoloads - If IncludeSingletons is enabled
  4. Static Classes - If IncludeClasses is enabled

Exposing Properties

Properties must have the [Export] attribute to be visible to the Dialogue Manager.
[Export] public string PlayerName { get; set; } = "Player";
[Export] public int PlayerHealth { get; set; } = 100;
[Export] public bool HasKey { get; set; } = false;
In your dialogue:
Nathan: Hello {{PlayerName}}!
Nathan: You have {{PlayerHealth}} health.

if HasKey:
    Nathan: You can unlock the door.

Custom Mutations

Mutations should be async methods returning Task or Task<Variant>.
public async Task AskForName()
{
    var dialog = GD.Load<PackedScene>("res://ui/name_dialog.tscn")
        .Instantiate() as AcceptDialog;
    GetTree().Root.AddChild(dialog);
    dialog.PopupCentered();
    await ToSignal(dialog, "confirmed");
    PlayerName = dialog.GetNode<LineEdit>("NameEdit").Text;
    dialog.QueueFree();
}
Usage in dialogue:
do AskForName()
Nathan: Hello {{PlayerName}}!

Complete Example

Here’s a complete example of using the C# wrapper in a game:
using Godot;
using DialogueManagerRuntime;
using Godot.Collections;

public partial class DialogueController : Node
{
    [Export] public string PlayerName { get; set; } = "Player";
    [Export] public int PlayerHealth { get; set; } = 100;
    
    private Resource dialogue;
    
    public override void _Ready()
    {
        // Load dialogue
        dialogue = GD.Load<Resource>("res://dialogue/main.dialogue");
        
        // Set up event handlers
        DialogueManager.DialogueStarted += OnDialogueStarted;
        DialogueManager.DialogueEnded += OnDialogueEnded;
        DialogueManager.GotDialogue += OnGotDialogue;
        
        // Configure state resolution
        DialogueManager.IncludeSingletons = true;
    }
    
    public void StartDialogue(string startLabel = "start")
    {
        DialogueManager.ShowDialogueBalloon(dialogue, startLabel);
    }
    
    private void OnDialogueStarted(Resource resource)
    {
        GD.Print("Dialogue started");
        GetTree().Paused = true;
    }
    
    private void OnDialogueEnded(Resource resource)
    {
        GD.Print("Dialogue ended");
        GetTree().Paused = false;
    }
    
    private void OnGotDialogue(DialogueLine line)
    {
        GD.Print($"{line.Character}: {line.Text}");
        
        // Handle special tags
        if (line.HasTag("emotion"))
        {
            var emotion = line.GetTagValue("emotion");
            PlayEmotionAnimation(emotion);
        }
    }
    
    public async Task GiveItem(string itemName)
    {
        GD.Print($"Giving item: {itemName}");
        await ToSignal(GetTree().CreateTimer(1.0), "timeout");
    }
    
    private void PlayEmotionAnimation(string emotion)
    {
        // Play animation based on emotion
    }
    
    public override void _ExitTree()
    {
        // Clean up event handlers
        DialogueManager.DialogueStarted -= OnDialogueStarted;
        DialogueManager.DialogueEnded -= OnDialogueEnded;
        DialogueManager.GotDialogue -= OnGotDialogue;
    }
}

Additional Resources

Build docs developers (and LLMs) love