Quest Development Guide
Target audience: Quest developers joining the Antura project. Scope: Environment setup, folder structure, scene authoring, asset library usage, and quest wiring. Note: This guide assumes English-only development with no voice-over (no localization tables or audio assets required).
Read first: Quest Design Guide: covers design principles, the Yarn command reference, and the full content + scripting workflow. This development guide picks up where that one leaves off.
See also: Script Writing Guidelines: for dialogue polish and VO/localization workflows (not needed during English-only dev).
1. Unity Setup
Install Unity and the project as documented here
One-Time Editor Configuration
After first opening the project:
Play from Bootstrap only. Never press Play from a random scene. Set the bootstrap scene as default:
Edit → Project Settings → Editor → Default Play Mode Scene→Assets/_core/_scenes/app_Bootstrap
Set Game window to 16:9:
- In the Game view dropdown, pick 1920×1080 or any 16:9 ratio.
Addressables:
Window → Asset Management → Addressables → Groups- Set Play Mode Script → Fast Mode (avoids a full build for editor testing).
First-time Addressables build (required before making any player build):
Addressables Groups → Build → New Build → Default Build Script
Normalize audio addressables (run once, and after adding new audio):
Antura menu → Localization → Normalize Addressables
2. VS Code Setup
Required Extensions
| Extension | Publisher | Purpose |
|---|---|---|
| C# Dev Kit | Microsoft | Full C# IntelliSense, refactor, debug |
| Unity | Microsoft | Unity-specific code actions & debugger attach |
| YarnSpinner | YarnSpinner Team | Syntax highlighting & preview for .yarn files |
| GitLens | GitKraken | Inline blame, history, branch visualization |
| EditorConfig for VS Code | EditorConfig | Respects .editorconfig (4-space indent, LF) |
Recommended Extensions
| Extension | Purpose |
|---|---|
| TODO Highlight | Surfaces // (refactor): and // TODO: markers |
| Markdown All in One | Preview for _README design notes.md files |
| DotENV | Syntax for any .env config files |
VS Code ↔ Unity Integration
In Unity: Edit → Preferences → External Tools → External Script Editor → Visual Studio Code Click Regenerate project files to create .csproj files VS Code uses for IntelliSense.
3. Quest Folder Structure
Where Quests Live
All quests are under:
Assets/_discover/_quests/Quests are organized by country prefix and a sequential number:
_quests/
├── _Quests List.asset ← Central registry (add your quest here)
├── _DEV/ ← Sandbox for experimental quests
├── _TUTORIAL/ ← Tutorial quests
├── FR_00 Geo France/ ← Country overview quest
├── FR_01 Paris/ ← City quest
├── FR_02 Angers School/
├── PL_00 Geo Poland/
└── ...Creating a New Quest Folder
- Pick a prefix and number. Use the country ISO code + next available index, e.g.
IT_01. - Duplicate an existing quest folder (e.g.
FR_01 Paris) as your starting template. - Rename all files inside to match your new quest ID. Every file that contains the old quest name should be renamed. A typical quest folder after renaming:
IT_01 Rome/
├── IT_01 Rome - Quest Data.asset ← ScriptableObject (quest metadata)
├── IT_01 Rome - Quest Prefab.prefab ← Scene root prefab
├── IT_01 Rome - Yarn Project.yarnproject
├── IT_01 Rome - Yarn Script.yarn ← Dialogue & logic
├── IT_01 _README design notes.md ← Design notes (keep this!)
├── discover it_01 rome.unity ← Main scene
├── _activities/ ← Activity configs
├── _assets/ ← 3D models specific to this quest
├── _cards/ ← CardData ScriptableObjects
└── _topics/ ← TopicData ScriptableObjectsNaming conventions:
- Scene file:
discover xx_NN name.unity(all lowercase, spaces)- Asset files:
XX_NN Name - Asset Type.asset(Title Case, dash separator)- Prefab:
XX_NN Name - Quest Prefab.prefab
Register the Quest
Open Assets/_discover/_quests/_Quests List.asset in the Inspector and add your new QuestData asset to the list. Without this step, the quest won't appear in the game.
4. Quest Data ScriptableObject
The QuestData asset (.asset file) is the metadata hub for your quest. Create or configure it via the Inspector.
Key Fields to Fill (English-only, no VO)
| Field | Type | Notes |
|---|---|---|
Id | string | Unique slug, e.g. it_01_rome. Used in code and save data. |
IdDisplay | string | Short display ID shown in editor UI, e.g. IT_01 |
Status | enum | Set to Development while building; switch to Production when ready |
TitleEn | string | Quest title in English |
Country | enum | e.g. Italy |
Location | LocationData | Reference to a LocationData asset |
Thumbnail | AssetData | Reference thumbnail image |
Topics | List<TopicData> | 1–4 topic assets that define the knowledge content |
Cards | List<CardData> | Extra cards not covered by Topics |
Difficulty | enum | Tutorial, Easy, Normal, Difficult |
Duration | int | Estimated minutes |
targetAge | enum | Ages6to10 is typical |
Gameplay | List<GameplayType> | e.g. Seek, Story, Collect |
questPrefab | AssetReferenceGameObject | Addressable reference to the Quest Prefab |
YarnProject | YarnProject | The .yarnproject asset for this quest |
YarnScript | TextAsset | The .yarn file |
Leave blank for English-only / no-VO dev:
QuestStringsTable: no localization table neededQuestAssetsTable: no audio table neededTitle/DescriptionLocalizedString references, leave unset;TitleEnis sufficient
5. Game Library: AssetData, Cards, Topics, and Prefabs
The "Game Library" is the shared pool of reusable knowledge assets and 3D prefabs that quests reference rather than re-create.
Knowledge Hierarchy
TopicData
└── CoreCard (CardData)
└── Connections[] → CardData (place, person, object, event…)
└── Words[] → WordData (vocabulary)- A TopicData groups a cluster of related cards around a central concept.
- A CardData represents one knowledge unit (a monument, a dish, a historical figure, etc.).
- WordData is vocabulary linked to a card.
CardData Assets
Global cards live in Assets/_discover/_data/Cards/. Quest-specific cards go in the quest's own _cards/ subfolder.
To create a new card:
- Right-click in the Project panel →
Create → Antura → Discover → Card Data - Fill in:
Id,TitleEn,Type(Place, Person, Object, Event, Concept…),Country,Subjects,Importance - Link an
ImageAsset(reference anAssetDatapointing to the image) - Leave all LocalizedString fields empty for English-only dev
TopicData Assets
Quest-specific topics go in the quest's _topics/ subfolder. Global topics in Assets/_discover/_data/Topics/.
To create a topic:
- Right-click →
Create → Antura → Discover → Topic Data - Set
CoreCard - Add
Connections: each entry has aConnectedCard, aConnectionType(e.g.LocatedIn,CreatedBy,IsA), and aConnectionStrength(0.1–1.0)
AssetData: Images and Media
AssetData is a lightweight wrapper that points to actual sprites/textures via Addressables. Global assets are in Assets/_discover/_data/Assets/. Reference these from CardData.ImageAsset.
For new images (quest-specific art):
- Drop the image file into the quest's
_assets/folder - Mark it as an Addressable in the Inspector
- Create an
AssetDataScriptableObject pointing to it - Reference that
AssetDatafrom your card
3D Prefabs in Scenes
Reusable 3D objects live in Assets/_discover/Prefabs/. The main categories:
| Folder | Contents |
|---|---|
3D Common Prefabs/ | Benches, trees, props usable in any scene |
Characters/ | Player avatar, NPCs, tutor characters |
Interactive/ | Collectible items, doors, levers, triggers |
Country Prefab/ | Country-specific building templates |
Quest Special/ | One-off prefabs for specific quests |
To add a prefab to a scene: drag it from the Project panel into the scene or hierarchy. For interactive objects, ensure the prefab has a Collider and the appropriate interaction script attached.
6. YarnSpinner: Writing Quest Dialogue
Dialogue and quest logic are written in .yarn files using the YarnSpinner format.
File Setup
Every quest has two Yarn files:
XX_NN Name - Yarn Script.yarn: your dialogue and logicXX_NN Name - Yarn Project.yarnproject: the project file that groups scripts
The project file must reference the script file. Open the .yarnproject asset and ensure your .yarn file is listed under Source Files.
Node Anatomy
Each Yarn node maps to one dialogue moment or interaction:
title: quest_start
position: 0,0
tags:
type: panel
color: red
actor: NARRATOR
---
<<set $TOTAL_COINS = 0>>
<<area area_intro>>
Welcome to Rome! Let's explore the Colosseum.
<<target marker_colosseum>>
Follow the arrow to reach our first stop.
===Required header fields:
| Field | Description |
|---|---|
title | Unique node name used in <<jump>> and task references |
type | panel (full-screen), text (bubble), choice, quiz, panel_endgame |
color | Editor color coding: red, blue, green, yellow |
actor | Who is speaking: NARRATOR, TUTOR, or an NPC id |
English-only: Write dialogue text directly in the node body. No
#line:xxxtags needed, only required for audio/localization lookup.
Common Yarn Commands
| Command | Example | Effect |
|---|---|---|
<<set>> | <<set $met_guide = true>> | Set a variable |
<<declare>> | <<declare $coins = 0>> | Declare with default value |
<<card>> | <<card colosseum>> | Display a knowledge card |
<<asset>> | <<asset map_image>> | Show an image |
<<target>> | <<target marker_id>> | Point navigation arrow at marker |
<<area>> | <<area area_gate>> | Activate an interactive zone |
<<action>> | <<action taskStart task_collect>> | Fire a quest action |
<<trigger>> | <<trigger sfx_fanfare>> | Fire a named event |
<<inventory>> | <<inventory add bread>> | Add item to player inventory |
<<jump>> | <<jump talk_npc_1>> | Jump to another node |
<<if>> / <<else>> / <<endif>> | Conditionals |
Choices
title: talk_guide
type: choice
actor: TUTOR
---
Do you know what the Colosseum was used for?
-> Gladiator fights!
That's right! #line:correct
<<set $knows_colosseum = true>>
<<jump reward_correct>>
-> A marketplace?
Close, but no. It was actually an arena.
<<jump quest_continue>>
===Endgame Node
Every quest must have a panel_endgame node that triggers quest completion:
title: quest_end
type: panel_endgame
color: green
actor: NARRATOR
---
Great job! You explored the Colosseum and learned about Ancient Rome.
<<action questEnd>>
===7. Technical Quest Setup: Step by Step
This section covers how to wire everything together in Unity so the quest actually runs.
Step 1 - Create the Quest Scene
- Duplicate an existing scene (e.g.
discover fr_01 paris.unity) and rename it todiscover xx_nn name.unity. - Open the new scene. Remove France-specific geometry and prefabs.
- Keep the top-level manager objects:
QuestManager(or whatever the scene root manager is named)DialogueRunner(YarnSpinner)DiscoverDialoguePresenter- Player spawn point
Step 2 - Create the Quest Prefab
In the scene hierarchy, create a new empty GameObject named
QuestPrefab_IT_01_Rome.Add all quest-specific environment objects as children.
Drag this GameObject to
Assets/_discover/_quests/IT_01 Rome/to create theIT_01 Rome - Quest Prefab.prefab.In
QuestData, setquestPrefabto reference this prefab's Addressable GUID.To make it Addressable: select the prefab → Inspector → check Addressable → assign to the
Discovergroup.
Step 3 - Hook Up YarnSpinner
- Select the
DialogueRunnerGameObject in the scene. - Set Yarn Project to
IT_01 Rome - Yarn Project. - Set Start Node to
quest_start(or whatever your opening node is named). - In
QuestData, set:YarnProject→ the.yarnprojectassetYarnScript→ the.yarnTextAsset
Step 4 - Define Tasks
Tasks are defined directly on GameObjects in the scene (not in ScriptableObjects). For each task:
- Create an empty GameObject under the
QuestManagerhierarchy, e.g.Task_CollectBread. - Add the
QuestTaskcomponent. - Configure:
Code- unique identifier used in Yarn:<<action taskStart task_collect_bread>>Type-Collect,Interact, orPerformance- For
Collect: setItemsContainer(parent of collectible objects) andItemCount - For
Interact: setInteractGO(the NPC or object to interact with) TaskNode- the Yarn node that describes this task to the playerNodeSuccess- Yarn node to jump to on completion
Collectible items must have:
- A
Colliderset to Is Trigger - The
CollectibleItem(or equivalent) component - An
ItemTagmatching the task'sItemTagfield
Step 5 - Interactive Areas
Interactive areas are trigger zones that fire Yarn nodes when the player enters them.
- Create an empty GameObject, add a
BoxCollider→ check Is Trigger. - Add the
DiscoverArea(orQuestArea) component. - Set
AreaIdto match the string used in<<area area_id>>in Yarn. - Optionally set an
OnEnterNode(Yarn node to jump to on entry).
Step 6 - Navigation Targets (Markers)
Directional arrows on-screen point the player to a target.
- Place an empty GameObject at the target location, e.g.
Marker_Colosseum. - Give it a descriptive name matching the string in
<<target marker_colosseum>>. - Register it with the
TargetManager(typically a component on theQuestManagerroot) - drag it into theTargetslist with a matching ID string.
Step 7 - World Setup (Optional)
To customize environment (time of day, weather):
- Create a
WorldSetupDataasset: right-click →Create → Antura → Discover → World Setup Data. - Configure
Time,Weather,Animals, etc. - Assign it to
QuestData.WorldSetup.
Step 8 - Register and Test
- Add the
QuestDataasset to_Quests List.asset. - Press Play from
app_Bootstrap. - Navigate to the Discover module and select your quest.
- Use the debug shortcut SHIFT+C in-editor to see available shortcuts for the current mode.
- Press
0/1/2/3to end a mini-game quickly when testing flow.
8. Knowledge Cards in a Scene (Inline Display)
When the player triggers a <<card card_id>> command in Yarn, the UI displays the card. The card_id must exactly match the Id field of a CardData asset that is referenced by the quest (via Topics or directly via QuestData.Cards).
Checklist for a card to display correctly:
- Card's
Idmatches the string in<<card id>> - Card is reachable from
QuestData(either inCardslist or in aTopicDatalinked fromTopics) - Card has
TitleEnfilled in - Card has an
ImageAssetassigned (or leave it null so the UI will show a placeholder)
9. Coding Conventions Reminder
When writing any C# scripts for a quest:
- Namespace:
Antura.Discover(orAntura.MiniGames.<GameName>for game logic) - 4-space indentation, Unix line endings
- Allman brace style for classes and methods; single-line
ifis fine for trivial guards - No copyright headers
- Leave a
// (refactor):comment if touching known unstable areas (seeCLAUDE.md) - Commit format:
feat(discover): add IT_01 Rome quest scene
10. Testing and Debugging
Playing the Quest in the Editor
Always press Play from Assets/_core/_scenes/app_Bootstrap, never from the quest scene directly. The bootstrap initialises all subsystems (database, player profile, teacher AI) that the Discover module depends on.
To speed up iteration:
- In the Debug panel (triple-click bottom-right of screen, requires
AppConstants.DebugPanelEnabled = true) you can jump directly to any quest. SHIFT+Cshows all available keyboard shortcuts for the current mode.SPACEskips intro/end panels.0/1/2/3force-ends an activity with 0–3 stars.
Jumping to a Specific Yarn Node
The DialogueRunner component (on the scene's manager root) has a Start Node field. Set it to any node title (e.g. step_c_start) to test mid-quest without replaying the whole flow. Remember to reset it to quest_start before committing.
You can also type a node title into the Yarn Graph editor's search bar and double-click to jump to it visually.
Common Problems and Fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Quest doesn't appear in the Discover menu | Not added to _Quests List.asset | Add QuestData to the list |
| Yarn script runs but quest doesn't load | questPrefab Addressable reference is empty or GUID is wrong | Re-assign in QuestData Inspector; rebuild Addressables |
<<card card_id>> shows nothing / placeholder | Card ID typo, or card not linked to QuestData | Check Id field on CardData exactly matches the command string; verify card is in Topics or Cards list |
<<area area_id>> doesn't restrict movement | Area ID case mismatch, or DiscoverArea component missing | IDs are case-sensitive; confirm component is on the collider object |
<<activity settings_id>> never starts | Activity Settings asset missing or ID mismatch | Create the asset via Create → Discover → Activity → [type]Settings; name must exactly match the command string |
<<target marker_id>> shows no arrow | Marker not registered in TargetManager, or ID mismatch | Add the marker GameObject to TargetManager's Targets list with the correct ID |
<<action action_id>> does nothing | Action not wired in ActionManager | Add an entry in the scene's ActionManager component pointing to the correct method/GameObject |
| Interactable doesn't open dialogue | Yarn Node Title field empty or wrong | Set it to exactly the node title in your .yarn file |
| Prefab changes not reflected in scene | Prefab instance overrides are blocking | In hierarchy, right-click prefab instance → Prefab → Revert |
| Addressables error on play | Fast Mode not set, or Addressables group not built | Addressables Groups → Play Mode Script → Fast Mode; rebuild if needed |
| Card audio plays but no text visible | TitleEn field is empty on CardData | Fill in TitleEn |
Quest freezes at a <<if>> block | Variable used without <<declare>> | Declare all quest-specific variables at the top of quest_start |
Testing the Full Flow Without VO or Localization
Since we're working English-only with no VO:
#line:tags on dialogue lines are not required during dev. The game will display the raw text without them.QuestStringsTableandQuestAssetsTablein QuestData can be left unassigned, the UI falls back toTitleEnand English text in the Yarn script.- Audio replay buttons will be inactive (no audio asset), this is expected behaviour during dev.
Useful Unity Console Filters
In the Console window, filter by these log prefixes to isolate quest-related output:
[QuestManager]: quest lifecycle events (start, end, task transitions)[YarnAntura]: Yarn command execution trace[Addressables]: asset loading errors[Activity]: activity launch and result events
Validating Before Committing
Before pushing a branch:
- Run the quest end-to-end at least once from
app_Bootstrap. - Confirm
quest_endis reached and the star/card screen appears. - Check the Unity Console has no errors (warnings are acceptable).
- Verify the quest
Statusfield in QuestData is still set toDevelopment(don't accidentally ship WIP content).
11. Quick Reference Checklist
When setting up a new quest from scratch, work through this list in order:
- [ ] Create quest folder
XX_NN Name/under_quests/ - [ ] Create
QuestDataasset, fillId,TitleEn,Country,Status: Development - [ ] Create
TopicData+CardDataassets in_topics/and_cards/ - [ ] Link Topics and Cards to QuestData
- [ ] Write
.yarnscript with at minimumquest_startandquest_endnodes - [ ] Create Yarn Project asset, link script to it
- [ ] Create quest scene, keep manager GameObjects, replace environment
- [ ] Build Quest Prefab from scene hierarchy, mark Addressable
- [ ] Assign
questPrefab(Addressable ref) in QuestData - [ ] Assign
YarnProjectandYarnScriptin QuestData - [ ] Add Tasks to scene for each gameplay objective
- [ ] Add Interactive Areas matching
<<area id>>commands - [ ] Add Navigation Markers matching
<<target id>>commands - [ ] Add QuestData to
_Quests List.asset - [ ] Play from
app_Bootstrapand verify quest appears and runs end-to-end