doc 7 of 10

Stage 05 — Charting by Playing

You will build: a recording mode — play the song, tap the lanes, and your taps become a chart you can immediately play back. You'll learn: building tools inside your game · runtime data hygiene — and you'll make design decision 3 from the architecture doc. Warm-up — from memory: which of the three latencies shifts judgment only, and why recording must care about it.

Why this exists#

The prototype had a recording feature that could never run — you proved that in the bug hunt. Now build the real one, because hand-placing beats in an inspector is how charts don't get made. Every real rhythm game charts by playing: the charter taps along, the game captures beat timestamps, and the captured taps are the chart. The subtlety — and the reason this is a stage, not a feature checkbox — is that your taps arrive late by your own input latency. Record them raw and every chart you make is systematically late; every future player inherits your keyboard's lag.

Build it#

A — The capture#

A recording mode (project setting, debug key, whatever you choose — deliberately): while the song plays, each lane press appends a NoteData with the current beat and lane. Decide consciously which beat you capture: raw song-time beat, or input-latency-corrected beat. One of them bakes your hardware into the data. The warm-up question is the answer.

B — Where the recording goes (decision 3)#

The architecture doc lays out the trap: writing into the loaded ChartResource mutates a shared resource at runtime — the exact anti-pattern the audit taught you. Decide where recorded notes live and how they become a real chart file, record the decision, then build it. Whatever you choose: recordings must survive the game closing, and must never write into res:// (exported games can't — the bug hunt's disk grinder already taught this; user:// exists for exactly this).

C — Playback#

Load a recorded chart and play it. First recording will be rough — that's signal, not failure. Re-record the same 20 seconds three times and watch your consistency improve; you're calibrating the charter (you) as much as the tool.

D — Round-trip check#

Record → close the game entirely → reopen → play the recording. If that works, your data pipeline is honest. Commit.

git add . && git commit -m "stage 05: chart recording with latency-corrected capture"

Checkpoint — definition of done#

  • A chart recorded by playing exists as a file, outside res://
  • It survives a full game restart and plays back correctly
  • You can state, in one sentence, why the captured beats were (or deliberately weren't) latency-corrected
  • Decision 3 recorded — and if you chose the buffer-then-promote route, one recorded chart has been promoted into the project and plays like any built-in song
  • The loaded built-in chart resource is never mutated — prove it: record over a built-in song, restart, confirm the original is intact

Stretch (no instructions)#

A metronome tick during recording (the conductor already knows the beat) — and notice what hearing the tick does to your tap accuracy.

If you get stuck#

  • Recorded notes all feel early on playback → you corrected latency twice (once at capture, once at judgment). Draw the signal path on paper: press → capture → save → load → judge. The correction belongs in exactly one arrow.
  • File isn't there after restart → print the absolute path you wrote to (ProjectSettings.globalize_path("user://...")) and go look at it in the file explorer.
  • Playback ignores the new chart → is the game still loading the .tres it always loads? Follow the chart from disk to the spawner by hand.