# 7. Rhythm Game Pitfalls Part of [[MIDI Rhythm Game]]. Prev: [[6. Latency Calibration and Worked Example]]. | Symptom | Cause | Fix | |---|---|---| | Notes stutter on the highway | Positions driven by raw `dspTime`, which moves in DSP blocks | Use `RhythmConductor.SongTime` (smoothed, monotonic) | | Song slowly drifts from visuals | Song position from `Time.time` or summed `deltaTime` | Everything from dspTime ([[2. Conductor and the dspTime Beat Clock]]) | | First beat late by a random amount | `PlayScheduled` time already in the past, or a streaming clip still opening | Schedule 0.1-0.2 s ahead plus a lead-in; preload; avoid Streaming load type for charts | | Every hit judged "late" by the same amount | No calibration, or track-mode value used in synth mode | Separate profiles ([[6. Latency Calibration and Worked Example]]) | | Hits judged by frame | Using "now" instead of `ctx.time` | Timestamped input ([[4. Note Highway Input and Judgement]]) | | MIDI pad hits feel looser than keys | Minis callback stamped at processing time | Bind Minis controls in actions if the Input Debugger shows usable paths | | Subharmonicon tempo doubles or wobbles | `MidiClockThread` **and** the sequencer clock both running | One clock source only | | Mother-32 drones after stop | Note Offs still queued when you cleared, or scene unloaded mid-note | `ChartMidiSequencer.StopAndSilence()` on pause, stop, unload, quit | | "No MIDI ports" / port busy | Another app (DAW, SysEx tool) owns the port; Windows MIDI ports are exclusive | Close the other app; see [[Eurorack and Unity]] 1.3.6 | | Notes play in the wrong octave on the Subharmonicon | It treats notes as offsets from C4 | Author the SUB track around MIDI 60 | | Late-song timing gets sloppy | `float` seconds | Keep `double` until positions | | Hold notes break randomly | Hold interaction on the lane action delays/changes callbacks | Plain Button actions | | Players learn to play late | Hit sounds that are themselves late | Visual hit feedback first; optional hit sounds offset by the track-mode latency | | Pause/resume desyncs | `AudioSource.Pause` but `DspStart` not shifted | `RhythmConductor.Pause/Resume` shifts `DspStart` | | App alt-tab breaks timing | Expected: dspTime pauses with the app | Nothing to do for OS pause; for in-game pause use the conductor | ## Design pitfalls (Level Up!) - **Difficulty by speed.** Faster scroll is not harder; denser charts are. Keep scroll speed as a player option ([[Accessibility]]). - **No rest.** A chart with no breathing room is the rhythm-game version of a level with no safe rooms (Level 9, [[Level Up! (Review)]]). - **Unreadable patterns.** If two notes in a lane are closer than your Good window, the chart is unfair; catch it with the editor check in [[3. Note Charts and MIDI File Import]]. - **Punishing exploration.** Stray taps cost nothing here on purpose. If you add a penalty, make it an explicit Hard-mode rule. ## Patterns recap Game Loop (song time vs frame time), Event Queue (the MIDI scheduler), Type Object (charts, windows), Observer (judge events), Object Pool (note views). See [[Game Programming Patterns (Review)]].