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

Configuration Guide

Configuration Guide

All NPC behavior is driven by ScriptableObject assets that you create and assign in the Inspector. This guide covers every configurable field.


NpcBrainConfig

Create via: Right-click > Create > AI NPC Brain > Brain Config
Script: Runtime/Core/NpcBrainConfig.cs

Provider Settings

Field Type Default Description
providerMode ProviderMode OpenAI_Default Controls which LLM backend is primary and whether fallback is allowed.

ProviderMode options:

Mode Behavior
OpenAI_Default Uses OpenAI if an API key is set, otherwise falls back to Ollama, then Mock.
Ollama_Fallback Same as OpenAI_Default (tries OpenAI first, Ollama second, Mock last).
Ollama_Only Only uses Ollama. No fallback.
OpenAI_Only Only uses OpenAI. No fallback.

OpenAI Settings

Field Type Default Description
openAiApiKey string "" Your API key. Leave empty if using Ollama only.
openAiModel string gpt-4o-mini Model ID. Options: gpt-4o-mini (fast/cheap), gpt-4o (smart), or any compatible model.
openAiBaseUrl string https://api.openai.com/v1 Override for Azure OpenAI or API-compatible proxies.

Ollama Settings

Field Type Default Description
ollamaBaseUrl string http://localhost:11434 Ollama server URL.
ollamaModel string llama3.1:8b Model name. Must be pulled locally first (ollama pull llama3.1:8b).

Generation Parameters

Field Type Default Range Description
temperature float 0.6 0–2 Controls randomness. Lower = more deterministic, higher = more creative. Recommended: 0.4–0.8 for NPC dialogue.
maxTokens int 350 Maximum tokens in the LLM response. Keep low (300–500) for snappy dialogue.
timeoutMs int 20000 Request timeout in milliseconds. Increase for slow models or high latency.

Event Limits

Field Type Default Description
maxEventsSuggested int 2 Maximum event suggestions the LLM is allowed to return.
maxEventsFired int 1 Maximum events that will actually be dispatched per turn.
fireConfidenceThreshold float 0.65 Minimum confidence (0–1) for an event to pass the confidence gate.

Memory Settings

Field Type Default Description
recentTurnsToInclude int 6 Number of recent conversation turns included in the prompt. More turns = better context but higher token cost.
maxMemoryFactsToStorePerTurn int 3 Cap on new memory facts the NPC can store from a single turn.
maxRelevantMemoriesInPrompt int 5 Number of stored facts included in the prompt for context.

Relationship Settings

Field Type Default Description
maxDeltaPerStat int 3 Maximum change to any single relationship stat (affinity, trust, fear, respect) per turn. Prevents the LLM from making huge jumps.

PersonaDefinition

Create via: Right-click > Create > AI NPC Brain > Persona Definition
Script: Runtime/Core/PersonaDefinition.cs

Field Type Description
npcId string Stable unique identifier. Used as the save-file key and referenced throughout the system. Example: npc_aurelia_alchemist.
displayName string Human-readable name shown in the chat UI. Example: Aurelia.
personaJson string (TextArea) Free-form JSON blob injected into the LLM's developer prompt. This is where you define the NPC's personality.

Writing Good Persona JSON

The persona JSON is the most important piece of configuration. It directly shapes how the NPC speaks and behaves. Structure it with these keys:

{
  "role": "Alchemist shopkeeper in a quiet fantasy village",
  "traits": ["witty", "cautious", "secretly romantic"],
  "goals": ["sell potions", "find the Moonpetal flower", "protect her shop"],
  "speech_style": "Short, precise sentences. Dry humor. Occasionally trails off when nervous.",
  "backstory": "Inherited the shop from her mentor. Doesn't trust strangers easily.",
  "vendor_type": "alchemy",
  "romance_eligible": true,
  "quest_giver": true
}

Tips: - Keep it concise. The entire persona JSON goes into every prompt. - traits should be 3–5 adjectives that strongly define personality. - speech_style is critical — it controls the NPC's voice. - Add custom keys freely. The LLM will use anything relevant.


NpcEventCatalog

Create via: Right-click > Create > AI NPC Brain > Event Catalog
Script: Runtime/Core/NpcEventCatalog.cs

The catalog is a whitelist of game events. Only events listed here can be suggested by the LLM and fired at runtime.

Event Definition Fields

Field Type Description
eventId string Unique event identifier, e.g. shop.open.
description string (TextArea) Human-readable description included in the LLM prompt so it knows when to suggest this event.
args List<CatalogArgDef> Argument schema: name, type, and optional allowed values.

Argument Types

ArgType Validation
String Always passes.
Int Must parse as int.
Float Must parse as float.
Bool Must parse as bool (true/false).

Allowed Values

If allowedValues is non-empty on an arg, the provided value must be one of those strings. This is how you constrain animation IDs, shop IDs, etc.

See Event System for details on how events flow through validation.


NpcAnimationMap

Create via: Right-click > Create > AI NPC Brain > NPC Animation Map
Script: Scripts/NpcAnimationMap.cs

Maps semantic animation IDs to Animator trigger parameter names.

AnimTriggerBinding Fields

Field Type Description
animId string Semantic ID used in event payloads. Example: nod.
animatorTrigger string Actual Animator parameter name. Example: Nod.
usageHint string (TextArea) Hint included in the LLM prompt so it knows when to pick this animation. Example: "Use when agreeing or confirming."
moodTag AnimationMoodTag Broad mood category: Neutral, Positive, Negative, Unsure, Greeting, Farewell, Curious, Emphatic.

Use the editor tool Tools > AI NPC Brain > NPC Animation Setup to auto-fill this from an Animator Controller. See Editor Tools.


NpcUiBindings

Create via: Right-click > Create > AI NPC Brain > NPC UI Bindings
Script: Runtime/Npc/NpcUiBindings.cs

Stores the canonical window IDs for an NPC's UI panels.

Field Type Description
npcId string NPC identifier. Example: npc_aurelia_alchemist.
shopWindowId string Window ID for the shop panel. Example: npc_aurelia_alchemist.shop.
questBoardWindowId string Window ID for the quest board panel.
relationshipWindowId string Window ID for the relationship panel.
autoGenerateFromNpcId bool If true, clicking "Auto-Generate IDs" will fill the window IDs from the npcId.

WindowRegistry

Create via: Right-click > Create > AI NPC Brain > Window Registry
Script: Runtime/Core/WindowRegistry.cs

A ScriptableObject-based mapping of window IDs to panel GameObjects. Use WindowRegistryRuntime (MonoBehaviour) for scene-based panels instead.


Relationship State

Relationship scores are tracked per NPC-player pair and persisted to disk. They are not configured directly — they evolve through conversation.

Stat Range Description
affinity -100 to 100 How much the NPC likes the player.
trust 0 to 100 How much the NPC trusts the player.
fear 0 to 100 How afraid the NPC is of the player.
respect 0 to 100 How much the NPC respects the player.
stage string Narrative stage: acquaintance, friend, rival, etc.
flags List\<string> Narrative flags the LLM can add/remove (e.g. knows_player_name, completed_first_quest).

Each turn, the LLM returns a relationship_delta that adjusts these scores. The delta for each stat is clamped by maxDeltaPerStat before applying.


World State

The worldStateCompact field on AiNpcBrain is a free-form text area that gets injected into the prompt. Use it to tell the NPC about the current state of the game world:

Time: evening
Weather: raining
Player inventory: 3 healing potions, rusty sword
Recent event: bandits attacked the village

Update this string from your game systems as needed. Keep it concise to minimize token usage.