Narrative Engine¶
Skill ID: ivx-narrative-engine
name: ivx-narrative-engine description: >- Add branching dialog, story state machines, and narrative tools to IntelliVerseX SDK games. Use when the user says "dialog system", "branching dialog", "conversation tree", "story state", "narrative engine", "character relationships", "Ink import", "Yarn Spinner", "quest dialog", "cutscene", "visual novel", "dialog editor", "story flags", "NPC conversation", or needs help with any narrative or dialog system. version: "1.0.0" author: "IntelliVerse-X team@intelli-verse-x.ai" allowed-tools: - Read - Write - Edit - Glob - Grep - Shell
Overview¶
The Narrative Engine provides a complete dialog and story system with branching conversations, persistent story state, character relationship tracking, and AI-assisted dialog generation. It supports importing from industry-standard formats (Ink, Yarn Spinner) and includes a visual conversation editor for Unity.
IVXNarrativeManager (orchestrator)
│
├── IVXDialogManager → Branching conversation playback
├── IVXStoryState → Flags, variables, conditions
├── IVXConversationTree → Node graph data structure
├── IVXCharacterRelationship → Affinity tracking
├── IVXCutsceneSequencer → Timed narrative events
└── IVXNarrativeAI → AI dialog generation
│
▼
IVXLocalizationManager (localized strings)
1. Configuration¶
IVXNarrativeConfig ScriptableObject¶
Create via Create > IntelliVerseX > Narrative Configuration.
| Field | Description |
|---|---|
EnableNarrative | Master toggle |
DialogFormat | IVXNative, Ink, YarnSpinner |
AutoAdvanceDelay | Seconds before auto-advancing non-choice dialog (0 = manual) |
TypewriterSpeed | Characters per second for typewriter effect (0 = instant) |
EnableVoiceover | Integrate with IVXAIVoiceServices for TTS dialog |
EnableAIDialog | Allow AI-generated dialog for dynamic NPCs |
PersistState | Save story state to Nakama storage |
MaxRelationshipValue | Cap for relationship affinity (default 100) |
2. Conversation Trees¶
Defining Conversations¶
using IntelliVerseX.Narrative;
var tree = new IVXConversationTree("merchant_greeting");
var root = tree.AddNode(new DialogNode
{
Speaker = "merchant",
Text = "Welcome, traveler! What brings you to my shop?",
});
var buyOption = tree.AddChoice(root, new ChoiceNode
{
Text = "I'd like to buy something.",
Condition = null,
});
var sellOption = tree.AddChoice(root, new ChoiceNode
{
Text = "I have items to sell.",
Condition = new StoryCondition("has_sellable_items", true),
});
var rumorOption = tree.AddChoice(root, new ChoiceNode
{
Text = "Heard any interesting rumors?",
Condition = new StoryCondition("relationship.merchant", CompareOp.GreaterThan, 20),
});
tree.AddNode(buyOption, new DialogNode
{
Speaker = "merchant",
Text = "Excellent! Take a look at my finest wares.",
Action = new StoryAction("open_store"),
});
tree.AddNode(sellOption, new DialogNode
{
Speaker = "merchant",
Text = "Let me see what you've got...",
Action = new StoryAction("open_sell_panel"),
});
tree.AddNode(rumorOption, new DialogNode
{
Speaker = "merchant",
Text = "Well, between you and me... I heard strange noises from the old mine.",
Action = new StoryAction("unlock_quest", "investigate_mine"),
RelationshipChange = new RelationshipDelta("merchant", +5),
});
JSON Format¶
Conversations can also be defined in JSON:
{
"id": "merchant_greeting",
"nodes": [
{
"id": "start",
"speaker": "merchant",
"text": "dialog.merchant.greeting",
"choices": [
{ "text": "dialog.merchant.choice_buy", "next": "buy_response" },
{ "text": "dialog.merchant.choice_sell", "next": "sell_response",
"condition": { "flag": "has_sellable_items", "value": true } },
{ "text": "dialog.merchant.choice_rumors", "next": "rumors",
"condition": { "relationship": "merchant", "min": 20 } }
]
}
]
}
Text values prefixed with dialog. are resolved through IVXLocalizationManager.
3. Playing Dialog¶
IVXDialogManager¶
IVXDialogManager.Instance.OnDialogLine += (line) =>
{
dialogUI.ShowLine(line.Speaker, line.Text, line.Portrait);
};
IVXDialogManager.Instance.OnChoicesPresented += (choices) =>
{
dialogUI.ShowChoices(choices.Select(c => c.Text).ToList());
};
IVXDialogManager.Instance.OnDialogEnd += () =>
{
dialogUI.Hide();
};
await IVXDialogManager.Instance.StartConversationAsync("merchant_greeting");
Selecting Choices¶
4. Story State¶
IVXStoryState¶
Persistent flags and variables that control narrative flow:
IVXStoryState.Instance.SetFlag("met_merchant", true);
IVXStoryState.Instance.SetInt("quests_completed", 5);
IVXStoryState.Instance.SetString("player_title", "Dragon Slayer");
bool metMerchant = IVXStoryState.Instance.GetFlag("met_merchant");
int quests = IVXStoryState.Instance.GetInt("quests_completed");
Conditions¶
bool canAccess = IVXStoryState.Instance.Evaluate(new StoryCondition[]
{
new("met_merchant", true),
new("quests_completed", CompareOp.GreaterThanOrEqual, 3),
new("relationship.elder", CompareOp.GreaterThan, 50),
});
State Persistence¶
With PersistState enabled, story state syncs to Nakama storage for cloud save and cross-device continuity.
5. Character Relationships¶
IVXCharacterRelationship¶
Track player affinity with NPCs:
IVXCharacterRelationship.Instance.Modify("merchant", +10);
IVXCharacterRelationship.Instance.Modify("guard_captain", -5);
int merchantAffinity = IVXCharacterRelationship.Instance.Get("merchant");
Relationship Tiers¶
| Range | Tier | Effect |
|---|---|---|
| 0–19 | Stranger | Basic dialog only |
| 20–49 | Acquaintance | Rumors, minor quests available |
| 50–79 | Friend | Special prices, side quests |
| 80–100 | Trusted | Secret quests, unique items, lore |
Relationship Events¶
IVXCharacterRelationship.Instance.OnTierChanged += (character, oldTier, newTier) =>
{
Debug.Log($"{character}: {oldTier} → {newTier}");
ShowRelationshipNotification(character, newTier);
};
6. Ink and Yarn Spinner Import¶
Ink Import¶
var inkStory = await IVXNarrativeImporter.Instance.ImportInkAsync("Assets/Narratives/story.ink.json");
IVXDialogManager.Instance.StartInkStory(inkStory);
Yarn Spinner Import¶
var yarnProject = await IVXNarrativeImporter.Instance.ImportYarnAsync("Assets/Narratives/dialog.yarn");
IVXDialogManager.Instance.StartYarnNode(yarnProject, "MerchantGreeting");
Format Comparison¶
| Feature | IVX Native | Ink | Yarn Spinner |
|---|---|---|---|
| Branching dialog | Yes | Yes | Yes |
| Variables/flags | Yes | Yes | Yes |
| Localization | Built-in | Manual | Built-in |
| Visual editor | Yes (Unity) | Inky (external) | VS Code extension |
| AI generation | Yes | Export to Ink | Export to Yarn |
| Relationship tracking | Built-in | Custom functions | Custom commands |
| Voice integration | Built-in | Manual | Manual |
7. AI-Assisted Dialog¶
Dynamic Dialog Generation¶
For NPCs that need varied responses, use the AI subsystem:
var response = await IVXNarrativeAI.Instance.GenerateDialogAsync(new DialogGenerationRequest
{
NPC = "merchant",
PlayerMessage = "Do you have any fire-resistant armor?",
Personality = "shrewd, helpful, slightly greedy",
Context = new DialogContext
{
Relationship = IVXCharacterRelationship.Instance.Get("merchant"),
StoryFlags = IVXStoryState.Instance.GetAllFlags(),
RecentDialog = lastThreeLines,
},
});
dialogUI.ShowLine("merchant", response.Text);
Conversation Memory¶
AI dialog maintains conversation history per-NPC so responses stay contextually consistent within a session.
8. Cutscene Sequencer¶
IVXCutsceneSequencer¶
Timeline-based narrative events:
var cutscene = new IVXCutscene("intro_sequence");
cutscene.At(0f, new CameraAction("pan_to_village"));
cutscene.At(2f, new DialogAction("elder", "Our village has been peaceful for centuries..."));
cutscene.At(6f, new DialogAction("elder", "Until the shadows came."));
cutscene.At(9f, new CameraAction("pan_to_dark_forest"));
cutscene.At(10f, new SoundAction("thunder_rumble"));
cutscene.At(12f, new FadeAction(FadeType.Out, duration: 1f));
await IVXCutsceneSequencer.Instance.PlayAsync(cutscene);
Cutscene Actions¶
| Action | Description |
|---|---|
DialogAction | Show dialog line with speaker |
CameraAction | Move/rotate camera |
SoundAction | Play sound effect or music |
FadeAction | Fade in/out |
AnimationAction | Trigger character animation |
WaitAction | Pause for duration or input |
StoryAction | Set flags/variables |
SpawnAction | Instantiate objects |
9. Cross-Platform API¶
| Engine | Class / Module | Core API |
|---|---|---|
| Unity | IVXNarrativeManager | Full feature set + visual editor |
| Unreal | UIVXNarrativeSubsystem | Dialog, story state, relationships, Ink/Yarn |
| Godot | IVXNarrative autoload | Dialog, story state, relationships |
| JavaScript | IVXNarrative | Dialog, story state (JSON-based trees) |
| Roblox | IVX.Narrative | Dialog (via RemoteEvents), story state |
| Java | IVXNarrative | Dialog, story state |
| Flutter | IvxNarrative | Dialog, story state |
| C++ | IVXNarrative | Dialog, story state, relationships |
Platform-Specific Narrative¶
VR Platforms¶
| Feature | VR Guidance |
|---|---|
| Dialog UI | World-space dialog bubbles near NPC. No 2D overlay. |
| Choices | Gaze-select or controller-point to choose dialog options. |
| Cutscenes | Avoid taking camera control from the player. Use guided attention (audio cues, lighting) instead. |
| Voice | Spatial audio for NPC voices. Players naturally turn toward speakers. |
Console Platforms¶
| Feature | Console Guidance |
|---|---|
| Dialog speed | Support variable text speed and instant-reveal for accessibility. |
| Controller | D-pad for dialog choices. A/Cross to advance. B/Circle to skip. |
| Subtitles | Mandatory subtitle support with size and background options. |
WebGL / Browser¶
| Feature | WebGL Notes |
|---|---|
| Story state | Persist to localStorage or IndexedDB. Sync to Nakama on session end. |
| Dialog assets | Load conversation JSON on demand to reduce initial bundle size. |
| Voice | Use Web Speech API for client-side TTS as a lightweight alternative to AI voice. |
Checklist¶
-
EnableNarrativetoggled on inIVXBootstrapConfig - Dialog format chosen (IVX Native, Ink, or Yarn Spinner)
- Conversation trees defined for key NPCs
- Dialog UI connected to
IVXDialogManagerevents - Story state flags and variables defined
- Character relationships initialized with starting values
- Ink/Yarn files imported (if using external format)
- AI dialog tested for dynamic NPCs (if using AI)
- Cutscene sequences created for key narrative moments
- Dialog localized through
IVXLocalizationManager - VR world-space dialog UI implemented (if targeting VR)
- Console controller navigation for dialog tested (if targeting consoles)
- WebGL story state persistence configured (if targeting browser)