AI NPC Framework

Description

AI NPC Brain is a Unity-focused system that turns NPCs into LLM-driven characters: they chat in character, remember facts about the player, track relationship stats (affinity, trust, fear, respect, flags), and can suggest game actions as structured events. Those suggestions are validated against a whitelist (your event catalog) before anything runs, so the model can’t arbitrarily trigger unknown gameplay.

It ships with pluggable backends (OpenAI, local Ollama, and a mock fallback for offline/UI testing), file-based persistence for conversation and memory, sample UI, demo scene, and editor tools (e.g. animation/catalog setup).

Technical Features

  • LLM-backed NPC dialogue — NPCs reply in character from a persona you define (ScriptableObject + JSON), with OpenAI, local Ollama, or an offline mock for testing.
  • Persistent memory — Stores facts about the player across sessions (file-based), with limits so prompts stay bounded.
  • Relationship model — Tracks affinity, trust, fear, respect, narrative flags, and stage; each turn can apply clamped deltas from the model.
  • Structured, safe game events — The model returns JSON; only catalog-whitelisted events can fire, with typed args, optional allowed values, and a confidence threshold.
  • Conversation history — Rolling turn history in the prompt (configurable depth) plus relevant memories retrieval.
  • World context — worldStateCompact on the brain injects free-form game state into prompts (time, location, inventory snippets, etc.).
  • Unity integration — Central AiNpcBrain component with UnityEvents (OnNpcReply, OnEmotionChanged, OnAnyNpcEventPayload, etc.) for UI, animation, and gameplay hooks.
  • Animation bridge — NpcAnimationMap maps semantic animation IDs to Animator triggers; NpcAnimationReceiver plays them from validated events.
  • UI workflow — Sample TMP chat UIs (simple and scroll-view), optional window IDs and WindowRegistryRuntime for opening shop/quest/relationship panels.
  • Editor tooling — Tools > AI NPC Brain (e.g. NPC Animation Setup) to sync Animator triggers with the animation map and event catalog.
  • Demo content — Demo scene, sample assets, and prefabs so buyers can press Play after wiring an API key or Ollama.
  • Unity 6 + URP oriented — Documented for Unity 6 and URP, with standard dependencies (Input System, Newtonsoft JSON, TextMesh Pro).

Documentation

API Reference

API Reference

Complete reference for every script in the AI NPC Brain package, organized by folder.


Runtime/Core

AiNpcBrain.cs

Type: MonoBehaviour
Namespace: AiNpcBrain
Location: Runtime/Core/AiNpcBrain.cs

The central orchestrator. Accepts player text, builds prompts, queries an LLM provider, parses the structured response, updates memory and relationship state, and fires validated game events.

Inspector Fields

Field Type Description
persona PersonaDefinition The NPC's identity and personality.
config NpcBrainConfig Brain settings (provider, generation params, limits).
eventCatalog NpcEventCatalog Whitelist of allowed game events.
worldStateCompact string Free-form world state text injected into the prompt.
uiBindings NpcUiBindings Canonical window IDs for this NPC's UI panels.
animationMap NpcAnimationMap Animation ID to Animator trigger mappings.

Unity Events

Event Type Fired When
OnNpcReply UnityEvent<string> NPC reply text is ready.
OnEmotionChanged UnityEvent<string> NPC emotion tag changes (e.g. "happy", "sad").
OnDebugLog UnityEvent<string> Internal debug/error messages.
OnSafetyFallback UnityEvent<string> Fallback message when the pipeline fails.
OnAnyNpcEventPayload UnityEvent<string> Validated event JSON payload is dispatched.

Public Methods

Method Signature Description
SendAsync Task<string> SendAsync(string playerText) Sends plain text to the NPC. Returns the reply.
SendAsync Task<string> SendAsync(PlayerUtterance utterance) Full send with metadata (player ID, location, time).
SetPlayerId void SetPlayerId(string playerId) Changes the active player and reloads conversation state.
GetNpcId string GetNpcId() Returns the NPC's unique ID from the persona.
GetNpcShopId string GetNpcShopId() Returns the shop window ID (from bindings or fallback).
GetNpcQuestBoardId string GetNpcQuestBoardId() Returns the quest board window ID.
GetNpcRelationshipWindowId string GetNpcRelationshipWindowId() Returns the relationship window ID.
GetNpcRelationshipId string GetNpcRelationshipId() Alias for GetNpcRelationshipWindowId.

NpcDtos.cs

Namespace: AiNpcBrain
Location: Runtime/Core/NpcDtos.cs

Data transfer objects and interfaces used throughout the system.

Classes

PlayerUtterance — Incoming message from the player.

Field Type Description
text string The player's message text.
playerId string Player identifier.
location string Current in-game location.
timeOfDay string Current in-game time.

RelationshipDelta — Per-turn relationship score changes produced by the LLM.

Field Type Description
affinity int Change to affinity score.
trust int Change to trust score.
fear int Change to fear score.
respect int Change to respect score.
flags_add List<string> Flags to add to the relationship.
flags_remove List<string> Flags to remove from the relationship.

MemoryFact — A long-lived fact the NPC stores about the player.

Field Type Description
text string The fact text. Max 160 chars after sanitization.
tags List<string> Categorization tags.
entities List<string> Named entities referenced.
importance float 0–1, higher = more important.
unixTime long UTC epoch seconds when stored.

EventSuggestion — An LLM-suggested game event.

Field Type Description
event_id string Event identifier (must match catalog).
confidence float 0–1, gated by fireConfidenceThreshold.
args SerializableDict Key-value arguments for the event.

SerializableDict — Lightweight string-to-string dictionary compatible with JsonUtility.

Method Signature Description
Set void Set(string key, string value) Sets or overwrites a key-value pair.
TryGet bool TryGet(string key, out string value) Retrieves a value by key.

NpcModelResponse — Structured response parsed from LLM output.

Field Type Description
reply_text string The NPC's dialogue text.
emotion_tag string One of: neutral, happy, angry, afraid, sad, curious, disgusted, surprised.
relationship_delta RelationshipDelta Per-turn relationship changes.
memory_facts_to_store List<MemoryFact> Facts to persist.
event_suggestions List<EventSuggestion> Game events to potentially fire.

ModelRequest — Prompt payload sent to an LLM provider.

Field Type Description
system string System-level instructions.
developer string Developer prompt (persona, context, schema).
user string Player utterance and metadata.
maxTokens int Max response tokens.
temperature float Generation temperature.
timeoutMs int Request timeout.

ModelResult — Raw result from an LLM provider.

Field Type Description
ok bool Whether the request succeeded.
rawText string Raw response text.
error string Error message if failed.

Interfaces

INpcModelProvider — Abstraction for any LLM backend.

Member Description
string ProviderName { get; } Human-readable provider name.
Task<ModelResult> GenerateAsync(ModelRequest, CancellationToken) Sends a prompt and returns the raw result.

IMemoryStore — Persistence layer for conversation state.

Method Description
ConversationState Load(string npcId, string playerId) Loads conversation state (creates new if absent).
void Save(string npcId, string playerId, ConversationState) Saves state to disk.
void AppendTurn(string npcId, string playerId, Turn) Appends one turn and re-saves.
List<MemoryFact> Query(string npcId, string playerId, string query, int max) Returns relevant memory facts, newest first.

IPromptPolicy — Strategy for building prompts.

Method Description
(string, string, string) BuildPrompt(...) Returns (system, developer, user) prompt tuple.

IResponseValidator — Strategy for parsing LLM output.

Method Description
bool TryParseAndValidate(string raw, out NpcModelResponse, out string error) Parses and validates raw text.

NpcBrainConfig.cs

Type: ScriptableObject
Menu: Create > AI NPC Brain > Brain Config

See Configuration Guide for all fields.


NpcEventCatalog.cs

Type: ScriptableObject
Menu: Create > AI NPC Brain > Event Catalog

Method Signature Description
TryGet bool TryGet(string eventId, out EventDefinition def) Looks up an event by ID.

Supporting types: EventDefinition, CatalogArgDef, ArgType enum, StringEvent.


PersonaDefinition.cs

Type: ScriptableObject
Menu: Create > AI NPC Brain > Persona Definition

See Configuration Guide for all fields.


EventGate.cs

Type: static class
Namespace: AiNpcBrain
Location: Runtime/Core/EventGate.cs

Static validator for LLM-suggested events.

Method Signature Description
TryBuildPayload static bool TryBuildPayload(EventSuggestion, NpcEventCatalog, out string payload, out string reason) Validates an event suggestion against the catalog. Returns a JSON payload on success, or a reason string on failure.

StateModels.cs

Namespace: AiNpcBrain
Location: Runtime/Core/StateModels.cs

Turn — A single dialogue turn.

Field Type Description
role string "PLAYER" or "NPC".
text string The spoken text.
unixTime long UTC epoch seconds.

RelationshipState — Persistent relationship scores.

Field Type Range
affinity int -100 to 100
trust int 0 to 100
fear int 0 to 100
respect int 0 to 100
flags List<string> Narrative flags
stage string e.g. "acquaintance"
Method Description
void ApplyDelta(RelationshipDelta d, int maxDeltaPerStat) Applies clamped relationship changes and merges flags.

ConversationState — Full state for one NPC-player pair. Contains RelationshipState, List<Turn>, and List<MemoryFact>.

PlayerProfile — Optional player data (preferredName, pronouns, likes, dislikes).

WorldStateSnapshot — Compact world state string injected into prompts.


WindowRegistry.cs

Type: ScriptableObject
Menu: Create > AI NPC Brain > Window Registry

Method Signature Description
TryGetPanel bool TryGetPanel(string windowId, out GameObject panel) Finds the panel for a window ID.

WindowRegistryRuntime.cs

Type: MonoBehaviour
Namespace: AiNpcBrain

Scene-based window registry with Dictionary lookup.

Method Description
void BuildLookup() Rebuilds the internal Dictionary from serialized bindings.
bool TryGetPanel(string id, out GameObject panel) Looks up a panel by window ID.
void CloseAll() Deactivates every registered panel.

Runtime/Dialogue

DefaultPromptPolicy.cs

Type: class implementing IPromptPolicy
Location: Runtime/Dialogue/DefaultPromptPolicy.cs

Assembles the three-part prompt including persona, relationship, memory, conversation history, world state, event catalog, animation guidance, and output JSON schema.

DefaultResponseValidator.cs

Type: class implementing IResponseValidator
Location: Runtime/Dialogue/DefaultResponseValidator.cs

Parses raw LLM text into NpcModelResponse. Strips code fences, validates required fields, clamps values, and enforces the emotion tag whitelist: neutral, happy, angry, afraid, sad, curious, disgusted, surprised.


Runtime/Memory

JsonFileMemoryStore.cs

Type: class implementing IMemoryStore
Location: Runtime/Memory/JsonFileMemoryStore.cs

File-based persistence under Application.persistentDataPath/AiNpcBrain/{playerId}/{npcId}.json.

Limit Value
Max turns stored 30
Max memory facts stored 50

Runtime/Providers

OpenAiChatProvider.cs

Type: class implementing INpcModelProvider

Sends multi-role chat messages to any OpenAI-compatible /chat/completions endpoint. Uses UnityWebRequest for HTTP. Supports cancellation and timeout.

OllamaProvider.cs

Type: class implementing INpcModelProvider

Sends prompts to a local Ollama instance via /api/generate. Collapses system + developer + user into a single prompt string (Ollama's endpoint doesn't natively support multi-role chat).

MockProvider.cs

Type: class implementing INpcModelProvider

Offline mock for testing without an LLM. Returns canned responses based on keyword matching:

Keywords Intent Response
sell, buy, shop, vendor, wares Shop Opens shop event
quest, work, job, help, task Quest Offers quest event
relationship, how do you feel Relationship Opens relationship panel
gift, present, for you Gift Gift-giving event
(other) Default Generic listening response

Runtime/Npc

NpcUiBindings.cs

Type: ScriptableObject
Menu: Create > AI NPC Brain > NPC UI Bindings

Method Description
void AutoGenerate() Fills window IDs from the npcId (e.g. npc_id.shop, npc_id.quest_board, npc_id.relationship).

Runtime/UI

WindowPanelId.cs

Type: MonoBehaviour
Location: Runtime/UI/WindowPanelId.cs

Simple tag component. Attach to the root GameObject of any UI panel that should be discoverable by WindowRegistryRuntime. Set windowId to match the ID used in NpcUiBindings.


Runtime/Samples

SimpleChatUi.cs

Type: MonoBehaviour

Minimal chat UI: one TMP_InputField, one TMP_Text log, one OnSend() method. Good for quick prototyping.

NpcChatUiController.cs

Type: MonoBehaviour

Full-featured chat UI with ScrollView, message prefab instantiation, auto-scroll, Enter-to-send, and busy state management.


Scripts (Demo)

NpcAnimationMap.cs

Type: ScriptableObject
Menu: Create > AI NPC Brain > NPC Animation Map

Maps semantic animation IDs to Animator trigger names. See Configuration Guide.

Supporting types: AnimTriggerBinding, AnimationMoodTag enum.

NpcAnimationReceiver.cs

Type: MonoBehaviour
Location: Scripts/NpcAnimationReceiver.cs

Receives event payloads and translates anim.trigger events into Animator.SetTrigger() calls and anim.move_to events into world-space movement.

Field Type Description
animator Animator The NPC's Animator component.
npcRoot Transform The NPC's root transform for movement.
animationMap NpcAnimationMap Animation ID to trigger mapping.
playerAnchor Transform Target for "approach_player" movement.
idleAnchor Transform Target for "leave_player" movement.
stepDistance float Distance for step_forward / step_back. Default: 0.5.
moveSpeed float Movement speed in units/second. Default: 2.0.

AureliaDemoReceiver.cs

Type: MonoBehaviour
Location: Scripts/AureliaDemoReceiver.cs

Demo event receiver that routes events to UI panels. Handles shop, quest, relationship, and hint events. Supports Escape-to-close via the Input System.

DemoCursorUnlock.cs

Type: MonoBehaviour
Location: Scripts/DemoCursorUnlock.cs

Utility for demo scenes. Keeps the mouse cursor visible and unlocked every frame, overriding any character controller that tries to lock it.