Unclaimed Package Is this your package? Claim it to unlock full analytics and manage your listing.
Claim This Package

Install via UPM

Add to Unity Package Manager using this URL

https://www.pkglnk.dev/narrativegraphtool.git

README Markdown

Copy this to your project's README.md

Style
Preview
pkglnk installs badge
## Installation

Add **Narrative Graph Tool** to your Unity project via Package Manager:

1. Open **Window > Package Manager**
2. Click **+** > **Add package from git URL**
3. Enter:
```
https://www.pkglnk.dev/narrativegraphtool.git
```

[![pkglnk](https://www.pkglnk.dev/badge/narrativegraphtool.svg?style=pkglnk)](https://www.pkglnk.dev/pkg/narrativegraphtool)

README

πŸ“– Narrative Graph Tool

Narrative Graph Tool icon

A node-based narrative editor for Unity 6.4+ built on the Graph Toolkit. Design branching stories, dialogue, and interactive narratives visually β€” then play them back at runtime with a simple event-driven API.


✨ Features

  • πŸ—‚οΈ Visual graph editor with 14 node types
  • 🌿 Branching choices with conditional visibility
  • πŸ”’ Variable system β€” bool, int, float, string
  • 🎭 Extensible line metadata (emotions, portraits, voice, etc.)
  • 🎲 Random branching
  • ⚑ Event nodes for gameplay hooks
  • πŸ” Revisitable lines with alternate text
  • 🏷️ Jump/Target anchors for non-linear flow
  • πŸ“ Export any graph to plain text with one right-click
  • πŸ“¦ Zero runtime dependencies β€” pure C# data layer

πŸ“‹ Requirements

Requirement Version
Unity 6.4+
Graph Toolkit Built-in (Unity 6.4)

πŸ“¦ Installation

Go to Window β†’ Package Manager β†’ + β†’ Add package from git URL and paste:

https://github.com/marcusaasjensen/narrative-graph-tool.git

Graph Toolkit is built into Unity 6.4 β€” no extra steps needed.


πŸš€ Quick Start

1. Create a Narrative Graph asset

Right-click in the Project window β†’ Create β†’ Narrative Graph Tool β†’ Narrative Graph.

2. Open the graph editor

Double-click the .narrativegraph asset to open it in the graph editor.

3. Build your narrative

Add a StartNode, connect it to NarrativeLineNodes and EndNodes, wire up choices β€” the graph is automatically parsed and saved as a runtime NarrativeGraphData sub-asset whenever you save.

4. Set up the runner

Add a NarrativeRunner component to a GameObject, drag your .narrativegraph file into the Graph Data field.

5. Subscribe to events and drive your UI

using NarrativeGraphTool;

[SerializeField] NarrativeRunner runner;

void Start()
{
    runner.OnLine   += line   => Debug.Log($"{line.speaker}: {line.text}");
    runner.OnChoice += opts   => ShowChoiceUI(opts);
    runner.OnEnd    += ()     => Debug.Log("Narrative ended.");

    runner.VariableProvider = id => myVariables[id];
    runner.VariableSetter   = (id, val) => myVariables[id] = val;

    runner.StartNarrative();
}

void Update()
{
    if (Input.GetKeyDown(KeyCode.Space)) runner.Continue();
}

🧩 Node Reference

🟒 Flow

Node Description
Start Entry point of the narrative. Every graph needs exactly one.
End Terminates the narrative and fires OnEnd.

πŸ’¬ Lines

Node Description
NarrativeLine Displays a single line with a speaker, text, and optional metadata. Fires OnLine.
RevisitableLine Displays different text on first visit vs. subsequent visits. Fires OnLine.
NarrativeContext Groups a sequence of lines into a block. Fires OnBlock with all lines at once.

ℹ️ NarrativeContext is a container node β€” add LineBlock children inside it.


πŸ”€ Choices

Node Description
ChoiceContext Presents a list of choices to the player. Fires OnChoice. Optionally embed a Speaker, Prompt text, and Metadata directly on the node β€” or leave them empty and wire a NarrativeLine before it instead.
ConditionalBoolChoice A choice that only appears when a bool variable matches.
ConditionalIntChoice A choice that only appears when an int variable matches a condition.
ConditionalFloatChoice A choice that only appears when a float variable matches a condition.
ConditionalStringChoice A choice that only appears when a string variable matches a condition.

ℹ️ ChoiceContext is a container node β€” add ChoiceBlock or conditional choice children inside it.


πŸ”΅ Conditionals

Branch the flow based on a variable's value.

Node Compares
ConditionalBoolean Bool variable
ConditionalInteger Int variable with: == != < > <= >=
ConditionalFloat Float variable with: == != < > <= >=
ConditionalString String variable with: == != Contains

All conditional nodes have a True and False output port.


πŸ“ Set Variable

Modify a variable as the narrative flows through. Execution continues automatically.

Node Operations
SetVariableBool Set, Toggle
SetVariableInt Set, Add, Subtract, Multiply
SetVariableFloat Set, Add, Subtract, Multiply
SetVariableString Set, Append

🎲 Random Branch

Node Description
RandomBranchContext Picks one of its RandomBranchBlock children at random and continues from there.

⚑ Events

Node Description
Event Fires OnEvent with a name and optional string payload. By default auto-advances immediately. Enable Wait For Resume to stop the runner until Resume() is called β€” use this for animations, cutscenes, or any async effect that must finish before the narrative continues.

⏸️ Pause

Node Description
Pause Suspends the narrative without ending it. Fires OnPause. Call Resume() to continue from the connected output node. Use this to exit a dialogue mid-scene and re-enter exactly where you left off.

🏷️ Jump & Target

Node Description
Jump Teleports execution to a Target node by name.
Target A named anchor that execution can jump to.

πŸ’‘ Use Jump/Target for loops or shared nodes you want to revisit from multiple places.


βš™οΈ NarrativeRunner API

C# Events

Subscribe from code for full typed access to node data:

using NarrativeGraphTool;
using NarrativeGraphTool.Data;

// A single narrative line is ready to display
runner.OnLine += (NarrativeLineData line) => { };

// A sequential block of lines is ready to display
runner.OnBlock += (NarrativeBlockData block) => { };

// A choice menu should be shown β€” contains only the visible choices
runner.OnChoice += (ChoiceNodeData data) => { };

// An event node was reached β€” use name + payload for gameplay hooks
runner.OnEvent += (EventNodeData ev) => { };

// The narrative has ended
runner.OnEnd += () => { };

// A PauseNode was reached β€” runner stopped, waiting for Resume()
runner.OnPause += () => { };

πŸ”Œ Unity Events (Inspector)

Every C# event has an Inspector-wirable UnityEvent equivalent, visible under the Unity Events header on the NarrativeRunner component. Wire up any method directly in the Inspector β€” no code required.

Unity Event Equivalent C# event Parameter
_onLine OnLine NarrativeLineData
_onBlock OnBlock NarrativeBlockData
_onChoice OnChoice ChoiceNodeData
_onEvent OnEvent EventNodeData
_onNarrativeEnd OnEnd β€”
_onNodeEnter β€” NarrativeNodeData
_onNodeExit β€” NarrativeNodeData

ℹ️ _onNodeEnter and _onNodeExit fire for every node β€” useful for driving animations, audio, or analytics without caring about the specific node type. In the Inspector, select the Dynamic version of a method to receive the node as a parameter, or wire a no-parameter method to ignore it.


Controlling flow

runner.StartNarrative();              // Begin from StartNode
runner.StartNarrative(savedNodeId);   // Resume from a saved node
runner.Continue();                    // Advance past a line or block
runner.SelectChoice(index);           // Choose an option (0-based, filtered index)
runner.Resume();                      // Continue after a PauseNode or blocking EventNode
runner.SetGraphData(data);            // Swap graph data at runtime
runner.ResetVisitedNodes();           // Clear visit history

Blocking event example (animation, cutscene, close UI):

runner.OnEvent += ev =>
{
    switch (ev.eventName)
    {
        case "PlayCutscene":
            // ev.waitForResume is true β€” must call Resume() when done
            StartCoroutine(PlayCutsceneAndResume());
            break;

        case "PlaySound":
            // ev.waitForResume is false β€” runner already advanced
            audioSource.Play();
            break;
    }
};

IEnumerator PlayCutsceneAndResume()
{
    animator.Play("cutscene");
    yield return new WaitUntil(() => animator.IsInTransition(0) == false);
    runner.Resume();
}

Save & restore example:

// Save β€” store the current node ID anywhere (PlayerPrefs, JSON, ScriptableObject…)
string savedNodeId = runner.CurrentNode.id;

// Restore β€” resume exactly where the player left off
runner.StartNarrative(savedNodeId);

Variables

Provide callbacks so the runner can read and write your game's variables:

// Called when a conditional or set-variable node needs a value
runner.VariableProvider = (string id) => myVariables[id];

// Called when a set-variable node writes a value
runner.VariableSetter = (string id, object value) => myVariables[id] = value;

πŸ’‘ Variable IDs are plain strings you define in the graph nodes β€” they map to whatever storage system your game uses (Dictionary, ScriptableObjects, PlayerPrefs, etc.)


State

using NarrativeGraphTool.Data;

bool running                          = runner.IsRunning;
NarrativeNodeData current             = runner.CurrentNode;
IReadOnlyCollection<string> visited   = runner.VisitedNodes;

πŸ“ Export as Plain Text

Right-click any .narrativegraph asset in the Project window and choose Export Narrative As Text.

A .txt file is saved next to the asset and highlighted automatically. The output is a human-readable script that mirrors the graph flow:

=== MyGraph ===

[Alice]: What will you do?
> CHOICE
  [1] Fight
        [Alice]: Brave choice.
        === END ===
  [2] Run
        [Alice]: Live to fight another day.
        === END ===

All node types are supported β€” conditionals, set-variable, events, jumps, random branches, and cycle detection (↑ loops back to [label]).

You can also call it from code:

string script = NarrativeGraphTextExporter.Convert(myGraphData);

🎨 Custom Line Metadata

Attach game-specific data to any narrative line (emotion, portrait, audio clip, etc.) by extending NarrativeLineMetadata:

using NarrativeGraphTool.Data;

[CreateAssetMenu(menuName = "Narrative Graph > My Line Metadata")]
public class MyLineMetadata : NarrativeLineMetadata
{
    public Sprite portrait;
    public AudioClip voiceClip;
    public Color subtitleColor = Color.white;
}

Then assign it to a NarrativeLine or NarrativeContext node in the graph editor, and read it at runtime:

runner.OnLine += line =>
{
    if (line.metadata is MyLineMetadata meta)
    {
        portraitImage.sprite = meta.portrait;
        audioSource.PlayOneShot(meta.voiceClip);
    }
};

πŸ§ͺ Sample

The package includes a ready-to-use example in Samples/:

File Description
SimpleNarrativeUI.cs Minimal console-based runner showing the full API (input, choices, events, variables)

πŸ•ΉοΈ SimpleNarrativeUI controls: Space to advance, 1–4 keys to select choices.


πŸ“ Package Structure

NarrativeGraphTool/
β”œβ”€β”€ Editor/          # Graph editor nodes, parser, asset importer, text exporter
β”œβ”€β”€ Runtime/         # NarrativeRunner, NarrativeGraphData, node data classes
β”œβ”€β”€ Samples/         # SimpleNarrativeUI example
β”œβ”€β”€ Tests/           # Edit-mode unit tests (~90 tests)
└── Resources/       # Package icons

πŸ“„ License

MIT β€” see LICENSE for details.

Comments

No comments yet. Be the first!