Abyss Messenger Devlog: From "Paper Person" to "Playable Game"

This article records the full iteration that took Abyss Messenger from a "technical demo" to a "game you can actually play". Behind every change there is a painful little story.
Stage 1: is this game playable at all? (2026-06-30)
Problem: the character is a paper cutout
The game originally loaded a GLTF model (character.glb, 2.9 MB) in place of the procedural character. But that model carried no animation joint data (userData.joints), so while moving the character slid across the ground like a sheet of paper — no limb motion at all.
Fix: disable GLTF loading and use the procedural character only.
Problem: there is no gameplay
Two exploration agents audited the code end to end and concluded: at this point the game is a "walking dialogue simulator".
The core loop was: walk to an NPC → click through 8-13 lines of dialogue → get auto-teleported to the next NPC → repeat five times → choose between two endings → done.
Systems already present (all complete, none of them affecting gameplay):
- 5 landmarks + 5 NPCs + a 5-chapter linear main story + two endings
- A radio puzzle (tuning to 52.9 Hz only displays a paragraph of text; it unlocks nothing)
- A message-in-a-bottle system (written entirely by players; no preset story bottles)
Completely missing: no items or inventory, no puzzles that require decoding, no exploration rewards, no ability unlocks, no side quests, and no fail state or challenge of any kind.
Fix: rebuild the female character + add game systems
Character rebuild
buildCharacterMesh() was rewritten to construct a complete female character:
- A volumetric body: spherical hips + a conical torso + chest curvature (no longer a thin capsule)
- Long hair: a hair crown + a rear bundle (with swing animation) + side strands + bangs
- Clothing: a conical dress (with swing animation) + a decorative hem + a scarf + boots
- Accessories: a backpack + shoulder straps + a glowing letter (the player's own)
- Face: eyes (with highlight points) + a nose + lips
Each of the 5 NPCs was also given its own hair colour, dress colour and boot colour.
Animation system updates
- Walking: hip sway + hem flutter + long hair streaming + a natural gait
- Idle: a breathing animation + faint movement in the hair strands
- In dialogue: right-hand gestures + head tilts
New game systems
| System | What it is | How it works |
|---|---|---|
| Memory fragments | 12 glowing octahedra scattered across the planet's surface | Walk close and press E to collect; the HUD shows 0/12 |
| Quest items | 5 items (the tidal log / a fluorescence sample / the chronicle / a bone flute / a frequency meter) | The NPC refuses to talk until you have found the item |
| Story bottles | 7 preset narrative bottles (K's warning, Su Qing's diary, Ming Yue's sutra copying, and so on) | Placed around the planet; press B to pick one up |
| Consequences for the radio | Tuning to 52.9 Hz spawns a golden hidden fragment | Before unlocking: text only; after unlocking: a real item |
| Inventory | Shows the items you collected and the story of each fragment | Toggled with the I key |
What the preset story bottles say
Each of the 7 bottles holds one piece of the story:
- Anonymous: "If you found this letter, it means you heard that voice too. 52.9 hertz — it does not come from the seabed. It comes from somewhere deeper."
- K: "Seven lighthouses, seven gatekeepers. Lan City is only the beginning. Remember this frequency; it is the key."
- Su Qing (an old diary): "Brainwave data does not lie. This island is dreaming. And it is about to wake up."
- Ming Yue (a copied sutra): "The ten-thousand-year pact is due. The fate of the city on its back rests in the messenger's hands."
- K: "I have seen that door at the Lan City lighthouse. Do not open it. The same frequency means they are connected."
- Old Chen (a sailing log): "The tide went from six seconds to four, then to three. It is breathing faster and faster."
- Lin Xi (a memo): "Every clue points to the same conclusion — this is not an island, it is a living thing. And I have to choose."
Stage 2: the camera is wrong and the movement is strange (2026-07-01)
Diagnosis after ten minutes as an actual player
What happens when a real person enters the game?
| Time | What they do | What it feels like |
|---|---|---|
| 0-1 min | Title screen → enter the game | The title screen is fine; it has atmosphere |
| 1-2 min | Click the canvas to lock the mouse, walk with WASD | Confused: why is the ground curved? Why do I come back around after a few steps? |
| 2-3 min | Find the first glowing beacon | The beacon is obvious, but the walk to it makes you dizzy |
| 3-5 min | Talk to Old Chen (8 lines) | The story is good; the typewriter effect pulls you in |
| 5-5.5 min | Dialogue ends, auto-teleport | Jarring: how did I suddenly end up somewhere else? |
| 5.5-7 min | Look for the quest item + talk to Su Qing | Where is the item? No hint at all, so you wander blindly |
| 7-8 min | Collect one memory fragment | The fragment looks lovely glowing, but the text flashes by and is gone |
| 8-10 min | Third NPC dialogue | Repetitive: walk → read → teleport → walk → read → teleport... |
Root-cause analysis
Problem 1: the planet is too small
- Planet radius was only 18 units, a circumference of roughly 113 units
- Maximum speed 5.0 units/second → one lap of the planet in 23 seconds
- Camera distance 4.8 units, i.e. standing at 27% of the planet's radius away
- From that distance the ground visibly curves downward, as if you were on top of a giant ball
Problem 2: auto-teleport kills exploration
- Dialogue ends and you are teleported straight to the next NPC
- The player never needs to find a route themselves
- Exploration means nothing
Problem 3: no guidance for fragments and items
- 12 fragments scattered across the planet
- No map markers, no compass, no hints
- Only wandering and luck
Problem 4: dialogue cannot be skipped
- 8-13 lines of typewriter text
- Every line must finish typing before you can click to the next
- Extremely painful on a replay
Fix: a full overhaul
Planet scaled up 3x
PLANET_RADIUS: 18 → 50 (2.78x)
all 3D objects scaled uniformly by 2.5x
Every constant was rescaled in proportion:
| Constant | Old | New | Why |
|---|---|---|---|
| CAMERA_DISTANCE | 4.8 | 14 | Pull the camera back so more of the horizon is visible |
| CAMERA_HEIGHT | 1.6 | 5 | Raise the camera to reduce the sense of ground curvature |
| MAX_SPEED | 5.0 | 8.0 | Faster, but the planet is bigger so it feels slower relatively |
| JUMP_FORCE | 7.4 | 12 | Jump force matched to the heavier gravity |
| GRAVITY | 18 | 28 | More gravity, so jumps stop feeling floaty |
| INTERACT_DISTANCE | 2.5 | 6 | Interaction range matched to a bigger world |
| Landmark detection range | 7.4 | 20 | Detection radius matched to a bigger world |
Movement and camera fixes
- Camera collision: minimum distance 2.0 → 5.0, so the ground no longer yanks the camera in aggressively
- Character rotation: lerp coefficient 10 → 4, giving smoother turns
- Fog distance: 34/126 → 50/200, matched to the bigger world
- Camera far plane: 240 → 400
Auto-teleport removed
The teleportToQuest() calls were deleted. The player now has to navigate to the next objective themselves.
New navigation system
- Compass component: top-right corner shows a live arrow toward the objective plus the distance in metres
- Minimap markers: fragments (blue dot) / items (gold dot) / the target NPC (large pink dot)
- Objective direction API:
getTargetDirection()returns an angle and a distance
Beginner tutorial
On first entry the game shows a 4-step control guide:
- You are standing on a tiny planet. Move with WASD, turn the view with the mouse.
- Follow the glowing beacons to find NPCs, and press E to talk.
- Collect glowing memory fragments and quest items; press I to open your inventory.
- The compass in the top-right corner points you to the next objective.
Skip button for dialogue
A "Skip" button was added to the top-right of the dialogue panel; clicking it reveals the full text immediately.
Stage 3: every character is lying down (2026-07-01)
Problem: character orientation is completely wrong
After fixing the above, entering the game revealed: every character was lying flat, feet pointing up.
Root cause: a left-handed coordinate system
// the original code
const right = crossVectors(facing, normal) // facing × normal = LEFT (not RIGHT!)
This produced a left-handed matrix (determinant = -1). Three.js setFromRotationMatrix cannot handle a left-handed matrix correctly, so the characters ended up facing the wrong way entirely.
Fix: a right-handed coordinate system
// after the fix
const right = crossVectors(normal, facing) // normal × facing = RIGHT (correct)
Swapping the order of the cross product yields a proper right-handed basis, and the characters stand correctly on the sphere.
Stage 4: only half a person, the lower body sunk in (2026-07-01)
Problem: the character is half buried
With orientation fixed, the character's upper half was visible and the lower half had sunk into the ground.
Root cause: wrong position maths
The character's position was set at normal × PLANET_RADIUS, which puts the character's origin (y=0) on the surface. But the boot soles sit 0.34 units below the origin, so the boots sank into the ground.
Fix: lift the character
// after the fix
const surfacePosition = normal.clone().multiplyScalar(PLANET_RADIUS + 0.4 + this.jumpOffset)
Raising the character by 0.4 units puts the boot soles exactly on the surface. The NPCs' position offset was fixed in the same pass.
Full change list
Engine.js (core engine)
| Change | Details |
|---|---|
| Character rebuild | Female character (dress / long hair / scarf / boots / female proportions), eliminating the paper cutout |
| GLTF disabled | Procedural character only, so an animation-less model cannot override it |
| Animation system | Hip sway / hem / hair while walking; breathing plus faint hair motion while idle |
| Memory fragments | 12 glowing octahedra, collected with E when close |
| Quest items | 5 items; NPCs demand you find them before they will talk |
| Story bottles | 7 preset narrative bottles |
| Radio consequences | 52.9 Hz unlocks a hidden fragment |
| Planet scaled up | Radius 18→50, all objects scaled uniformly by 2.5x |
| Camera fixes | Distance 4.8→14, height 1.6→5, more forgiving collision |
| Rotation smoothing | lerp coefficient 10→4 |
| Teleport removed | Replaced by compass navigation guidance |
| Navigation API | getTargetDirection / getShardPositions / getItemPositions |
| Orientation fix | Cross-product order corrected to a right-handed basis |
| Ground fix | Character raised by 0.4 units so the boot soles touch the ground |
App.vue (UI layer)
| Change | Details |
|---|---|
| Fragment counter HUD | Shows 0/12 in the top-right corner |
| Inventory panel | Toggled with the I key; shows items and each fragment's story |
| Compass component | Live direction arrow plus distance readout |
| Beginner tutorial | 4-step control guide on first entry |
| Dialogue skip | Top-right button that reveals the full text |
| Minimap markers | Fragments (blue) / items (gold) / target NPC (pink) |
| Pickup prompts | The banner that appears when you are near a fragment or item |
| Story overlay | The text shown after a fragment is collected |
i18n.js (bilingual strings)
Added 40+ bilingual entries:
- 12 fragment story texts
- 5 quest item names
- Tutorial text (the 4-step guide)
- UI text (inventory / compass / skip / distance and so on)
style.css (styling)
Added 176 lines of styles:
- Tutorial overlay (frosted background + card layout)
- Compass component (circular arrow + distance label)
- Skip button (translucent + hover state)
- Minimap markers (glowing dots)
- Inventory panel (sectioned layout + item cards)
- Story overlay (slides up from the bottom + fade-out animation)
Technical details
Build statistics
29 modules transformed
dist/assets/index.js 244.34 kB (gzip: 84.94 kB)
dist/assets/three.js 558.90 kB (gzip: 141.68 kB)
✓ built in 33.70s
Test verification
Playwright automated tests confirmed:
- ✅ 0 console errors
- ✅ Fragment counter 0/12 displays correctly
- ✅ Inventory toggles correctly with the I key
- ✅ Map toggles correctly with the M key
- ✅ WASD movement + spacebar jump work
- ✅ Tutorial overlay shows and dismisses correctly
Git commit history
The messages below are the original commits, quoted verbatim.
3318bb8 feat: 重建女性角色 + 新增记忆碎片/任务道具/故事漂流瓶游戏系统
c9ff436 feat: 新增背包UI + 碎片计数HUD + 收集提示交互
ca8b55a feat: 任务道具数据 + 双语翻译(碎片剧情/道具名称/UI文本)
d0a201d feat: 星球放大3倍 + 移动/相机修复 + 导航API
15d7407 feat: 新手教程 + 指南针导航 + 对话跳过 + 小地图标记
730757b fix: 修复角色朝向 — 右手坐标系 + 脚踩地面
In one sentence
From a tech demo of "a paper cutout sliding around on a small ball" to a playable 3D exploration game with a female character, a collection system, navigation guidance and a tutorial.
Every step was an iteration driven by real player feedback. No perfectionism — only "this is the problem hurting the experience most, so fix it first".
If you are making an indie game too, I hope this log saves you a few of these detours. At least you know — you are not the only one fighting a paper cutout.