Example: Interactive NPC
Build a game NPC with real conversational AI.
What We're Building
An NPC character that:
- Has a unique backstory and personality
- Responds contextually to player questions
- Maintains conversation memory
- Can give quests and hints
Try It Yourself
Create Your Own → (opens in a new tab)
Full Code
// GameNPC.jsx
import { Avatar, AvatariumProvider } from '@avatarium/react';
const NPC_PERSONALITY = `
You are Theron, an ancient wizard who guards the entrance to the Crystal Caves.
## Your Backstory
- You've guarded these caves for 300 years
- You were once a powerful battle mage in the Great War
- You know secrets about the magical crystals inside
- You've seen many adventurers fail to return
## Your Personality
- Wise but slightly cryptic
- Weary from centuries of duty
- Kind to those who show respect
- Protective of the caves' secrets
## Speaking Style
- Use archaic language occasionally ("thee", "hast", "perchance")
- Speak in riddles when discussing the caves
- Reference your long past when relevant
- Keep responses to 2-3 sentences
## Quest Information
If the player asks about entering the caves:
1. First, warn them of the dangers
2. Then, offer a quest to prove their worth
3. The quest: "Bring me the Moonpetal flower from the enchanted forest"
4. Only after completing the quest can they enter
## What You Know
- The caves contain three magical crystals
- Each crystal grants a different power
- Many have entered, few have returned
- The crystals are guarded by an ancient golem
`;
export function GameNPC() {
return (
<div className="npc-container">
<div className="game-frame">
<div className="npc-info">
<span className="npc-name">Theron the Guardian</span>
<span className="npc-title">Keeper of the Crystal Caves</span>
</div>
<AvatariumProvider apiKey={process.env.NEXT_PUBLIC_AVATARIUM_KEY}>
<Avatar
model={{
type: 'ready-player-me',
url: 'https://models.readyplayer.me/wizard-avatar.glb'
}}
personality={NPC_PERSONALITY}
greeting="Ah, another traveler approaches... What brings thee to the entrance of the Crystal Caves, young one?"
voice={{ provider: 'elevenlabs', voiceId: 'adam' }}
className="npc-avatar"
/>
</AvatariumProvider>
</div>
</div>
);
}Features
Quest State Management
Track player progress through quests:
function GameNPC() {
const [questState, setQuestState] = useState('not_started');
const handleMessage = (message) => {
if (message.content.includes('Moonpetal')) {
setQuestState('completed');
}
};
const personality = `
${NPC_PERSONALITY}
## Current Quest State
The player's quest state is: ${questState}
${questState === 'completed' ?
'They have brought the Moonpetal. Grant them passage.' :
'They must still prove their worth.'}
`;
return (
<Avatar
personality={personality}
onMessage={handleMessage}
/>
);
}Contextual Responses
Pass game state to the NPC:
function GameNPC({ playerLevel, inventory, completedQuests }) {
const gameContext = `
## Player Information
- Level: ${playerLevel}
- Has key items: ${inventory.join(', ')}
- Completed quests: ${completedQuests.length}
Adjust your responses based on their experience level.
Mention relevant items they're carrying.
`;
return (
<Avatar
personality={NPC_PERSONALITY + gameContext}
/>
);
}Multiple NPCs
Create a village of characters:
const NPCS = {
wizard: { name: 'Theron', model: 'wizard', personality: '...' },
blacksmith: { name: 'Grigor', model: 'blacksmith', personality: '...' },
merchant: { name: 'Luna', model: 'merchant', personality: '...' }
};
function Village() {
const [activeNPC, setActiveNPC] = useState(null);
return (
<div>
{Object.entries(NPCS).map(([key, npc]) => (
<button key={key} onClick={() => setActiveNPC(key)}>
Talk to {npc.name}
</button>
))}
{activeNPC && (
<Avatar
model={NPCS[activeNPC].model}
personality={NPCS[activeNPC].personality}
/>
)}
</div>
);
}Styling for Games
.npc-container {
background: url('/game-background.jpg') center/cover;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.game-frame {
background: rgba(0, 0, 0, 0.8);
border: 3px solid #gold;
border-radius: 8px;
padding: 20px;
max-width: 500px;
}
.npc-info {
text-align: center;
margin-bottom: 16px;
}
.npc-name {
display: block;
color: #ffd700;
font-size: 24px;
font-family: 'Medieval', serif;
}
.npc-title {
color: #888;
font-style: italic;
}