Inspiration

Bad NPCs create the illusion that a player is alone in a world that’s supposed to be alive.

They walk through each other. They repeat the same three lines. They stare blankly through the player. They don’t react when the world changes around them.

For small and mid-sized studios, building believable NPCs is expensive. Complex animation systems, dialogue trees, behavior scripting, and edge-case handling have to be repeated for every character.

We don’t think reality should limit developer imagination: Playable.exe is meant to make every character feel alive. We wanted to make a tool that allows small teams to deliver deeply immersive, emotionally intelligent characters without huge budgets. We aim to make NPCs more than just background fillers. We make them context aware and reactive personalities that evolve alongside the player.

What it does

Playable.exe is an AI NPC engine that converts character context into dialogue, animation, and environmental interaction inside Unity. (see more at https://playablehacklytics.vercel.app/) Developers define personality traits, backstory, emotional baselines, and narrative constraints, which are passed into a controlled language model layer that generates high level intent for the character. This intent is translated into executable game actions, animation state changes, NavMesh movement, object interactions, posture adjustments, and facial expression modifiers, bringing the character to life. NPCs interact with Unity world events and tagged objects, allowing them to react dynamically to player proximity, environmental triggers, time based events, and other NPC behaviors without hardcoded dialogue trees. Guardrails and edge parameters prevent jailbreaks and ensure outputs remain within developer defined lore and gameplay boundaries.

How we built it

We built Playable.exe using Next.js 15, TypeScript 5, React 19, and Tailwind CSS, with Zod ensuring strict schema validation across the system. NPC data is stored in a file-based structure without a traditional database, while Vercel Blob handles larger assets and Databricks processes analytics.

Core loop: Author NPC definitions in the web UI → persist them → Unity game calls the /api/npc/chat endpoint at runtime → Google Gemini (gemini-2.5-flash) generates structured JSON responses (dialogue, mood, gestures, actions) constrained by a Zod schema converted to JSON Schema via zod-to-json-schema.

Data layer: Dual-mode storage abstraction in src/lib/storage.ts — reads/writes data/npcs.json locally, swaps to Vercel Blob when BLOB_READ_WRITE_TOKEN is set. All writes are serialized through a custom mutex (src/lib/mutex.ts) to prevent race conditions.

NPC schema (Zod-validated): id, name, role, persona (backstory/goals/voice_style), rules (do_not[], spoiler_policy), capabilities (allowed gestures + actions as enums), lore_facts[], timestamps.

Databricks

Databricks is used for analytics. When you want to analyze your NPC list, the app can sync all NPC data into a Databricks warehouse. From there, the analytics dashboard (or any external tool) can run SQL queries against that data to surface insights, generate reports, or power the charts on the /data page. https://youtu.be/mYsyEq98S3w

Gemini

Gemini powers the NPCs' ability to talk. When a player walks up to an NPC in the game, it sends the conversation to Google's Gemini AI. The system feeds Gemini everything about that NPC and Gemini responds in character with a line of dialogue, a mood, a gesture, and an intent (like answering a question or giving a quest). NPCs can also "think aloud" in an ambient mode when no player is nearby.

Challenges we ran into

Unity supports a large variety of underlying models to create NPCs, which means there is no single standardized “NPC structure.” Supporting different humanoid rigs, Animator controllers, URP vs. built-in rendering, and prefab hierarchies required building an abstraction layer that could translate model output into universally friendly animation triggers.

Accomplishments that we're proud of

We successfully built a full stack AI character engine without relying on a traditional database, keeping the system lightweight and deployable for indie teams. Additionally, we were able to render extremely high quality graphics in a very short time frame, using AI to take a month long process into a 36 hour one. Additionally, we're proud that we collectively were able to get over eight hours of sleep.

What we learned

We learned that building believable NPCs is requires thoughtful system design. Language models are powerful, but without structure, validation, and clear constraints, they create chaos instead of immersion. Separating high level intent from executable game actions forced us to think like both designers and engineers. We had to translate something probabilistic into something deterministic, creating incredibly complex acritecture.

We also learned that constraints are clarifying. Not using a traditional database, working within Unity’s varied animation systems, and building under tight time pressure pushed us to prioritize simplicity and modularity. Instead of overengineering, we focused on creating a lightweight, scalable layer that small teams could realistically adopt.

What's next for Playable.exe

  1. Expand application to other game engines (ect. Unreal, Godot, Roblox Studio)
  2. One-click installation process
  3. Integrate specialized LLM models for dialogue

Built With

Share this project:

Updates