Intelligent NPCs

Playpower Labs
Unity Developer
1
3 Months
Unity • C# • OpenAI GPT • AWS Polly • OpenAI Whisper • VFX Graph

Exploration of LLM-driven NPCs with voice input, dynamic dialogue, and gameplay-aware reasoning.

Fantasy 3D worlds where the player can explore different environments, interact with NPCs, and complete quests. Teleporters scattered around the levels teleports the player to a different environment.

The NPCs are powered by OpenAI & AWS, allowing for dynamic conversations and interactions. Players can ask questions, receive answers, and even play side quests of counting fruits which is managed by the AI itself. It evaluates the player's input if they are correct or not, want to play another round or quit the game, and so on.

You can download the Windows build, the web build doesn't support voice input.

Key Contributions

LLM-Powered NPC Interaction · AI Integration · Real-Time Dialogue

Flowchart from user input to using AI to outcome

  • Integrated OpenAI GPT, OpenAI Whisper, and AWS Polly into Unity to create intelligent NPCs capable of speech recognition, contextual dialogue, and real-time voice synthesis.
  • Designed a full interaction pipeline where player input (text or voice) is transcribed, reasoned upon, and synthesized back as NPC speech.
  • Enabled NPC-driven mini-quest flows by injecting gameplay context into LLM prompts.

Example Scenario

  • A fruit-seller NPC offers a counting mini-game.
  • Randomized fruit quantities are provided to the LLM as context.
  • Player responses are evaluated for correctness and intent (retry, quit, or continue).
  • NPC dialogue and quest flow adapt dynamically based on responses.
Proof-of-Concept Development · Systems Design · Rapid Iteration
  • Developed the complete proof-of-concept solo.
  • Focused on validating AI-driven NPC interactions inside a real gameplay loop.
  • Prioritized extensibility and clean system boundaries.
NPC Architecture · Data-Driven Design · Reusability
  • Implemented ScriptableObject-based NPC personas defining name, backstory, and personality traits.
  • Personality traits are reusable assets shared across multiple NPCs.
  • Built a single NPC prefab with multiple prefab variants (patrol, quest-giver, interactive).
  • Decoupled NPC identity, behavior, and abilities for scalability.
Interface-Driven Gameplay Contracts · Decoupling · Extensibility
  • Defined clear interaction and quest contracts using interfaces.
  • Enabled NPCs, world objects, and AI-driven systems to interact without concrete dependencies.

IQuest

  • Supports NPC-specific quest logic while keeping execution generic.
  • Allows LLM-driven NPCs to progress quests using natural language input.
1  public interface IQuest
2  {
3      bool IsActive { get; }
4      void OnQuestStart();
5      void OnQuestEnd();
6      void OnPlayerResponse(string response);
7  }

IInteractable

Applied uniformly across NPCs, doors, chests, and other interactive entities.

1public interface IInteractable
2{
3    void Interact();
4}
Abstract Base Systems · Shared Behavior · Controlled Inheritance
  • Used abstract base classes where shared state and behavior needed to be enforced.
  • Prevented duplication while allowing controlled specialization in concrete implementations.

Abstract Door System

Some Code Snippet
1public abstract class DoorBehaviour : MonoBehaviour
2{
3    private Animator animator;
4    private int animationHash;
5    private bool isOpen;
6
7    public event Action DoorStateChanged;
8
9    protected void OpenDoor()
10    {
11        if (isOpen) return;
12
13        if (animator) animator.SetBool(animationHash, true);
14        DoorStateChanged?.Invoke();
15        isOpen = true;
16    }
17
18    private void OnTriggerExit(Collider other)
19    {
20        if (!isOpen) return;
21
22        if (animator) animator.SetBool(animationHash, false);
23        DoorStateChanged?.Invoke();
24        isOpen = false;
25    }
26}
  • Centralizes animation and state logic.
  • Allows concrete classes (e.g. InteractableDoor, AutomaticDoor) to define triggering behavior.
  • Event-driven state changes enable extension without modifying base logic.