Guide
Game moving platform and elevator systems explained
Harbor Foundry shipped a vertical factory gauntlet where players rode a chain of three synchronized elevators to cross a spike pit. Playtest telemetry showed 38% drop-off on the second platform: riders jumped off with zero horizontal carry, missed the next ledge by half a tile, and respawned at the shaft bottom. Worse, standing on a descending platform while a ceiling crusher activated felt random — the crush volume used world-space overlap without subtracting platform velocity, so frame-perfect deaths read as bugs. Refactoring rider parenting, jump-off velocity inheritance, and crush gating tied to platform state lifted shaft completion from 38% to 81% and cut “unfair death” support tickets by 74%.
Moving platforms and elevators are among the oldest platformer primitives, yet they remain a top source of feel bugs: sliding off edges, jitter on dismount, desync in multiplayer, and ambiguous crush rules. This guide covers kinematic vs physics-driven motion, how to attach riders without breaking jump arcs, path-based and trigger-driven schedules, coupling with one-way platforms, networked determinism, the Harbor Foundry refactor, a technique decision table versus static tiles and bounce pads, pitfalls, and a production checklist.
What moving platforms actually do in a platformer
A moving platform changes the player’s reference frame. While grounded on one, world position is the sum of platform motion plus local offset. That sounds trivial until you add variable-gravity jumps, dash cancels, drop-through inputs, and physics materials that fight kinematic parenting. Good systems answer four questions every frame:
- Who is riding? — track grounded contacts on the platform collider, not generic trigger overlap.
- How is motion applied? — add platform delta to rider position, or parent transforms with careful unparent on jump.
- What velocity carries on exit? — inherit platform velocity into player velocity on jump, dash, or knock-off.
- What hazards interact? — crushers, spikes, and timers must use the rider’s effective world velocity.
Elevators are moving platforms with long vertical segments, wait states at endpoints, and often door or barrier coupling. Treat them as the same code path with different path assets and UI affordances (floor indicators, call buttons).
Kinematic vs physics-driven platforms
Kinematic (recommended default)
The platform moves along a scripted path each frame; collision is one-way or solid from above. Riders receive the platform’s delta position (and optionally delta rotation). Kinematic motion is deterministic, cheap, and easy to replay in netcode. Use physics layers so the platform does not get pushed by stacked rigidbodies.
Physics-driven (use sparingly)
A dynamic rigidbody platform driven by motors or constraints can react to player weight and external forces. It feels organic for seesaws and loose crates but introduces jitter, tunneling at high speed, and non-deterministic multiplayer. If you must use it, cap mass ratios, enable continuous collision detection, and still manually inject rider velocity on contact resolution.
Interpolation and render vs sim
Move platforms in fixed simulation steps; interpolate render transforms for
display. Applying motion only in Update while physics runs in
FixedUpdate causes the classic “player vibrates on
elevator” bug. Harbor Foundry fixed 11 ms of perceived jitter by moving
platform integration into the same fixed tick as the character controller.
Rider parenting and velocity inheritance
Two implementation patterns dominate production platformers:
Delta application (no transform parent)
Each frame, for every rider grounded on the platform, add
platform.position - platform.prevPosition to the rider position.
On jump, set rider.velocity += platform.velocity before applying
jump impulse. This preserves existing character-controller architecture and
avoids euler-angle parent bugs on rotating platforms.
Transform parenting
Parent the player transform to the platform while grounded; unparent on jump and copy world velocity. Simpler in scene graphs but breaks if animation root motion also writes world position, if camera follow assumes a static parent hierarchy, or if drop-through temporarily disables collision — the player may remain parented while falling through. Always unparent on jump input edge, not on leaving ground contact alone.
Jump-off carry tuning
Full inheritance (v_player += v_platform) is correct for horizontal
shuttles. For fast vertical elevators, designers often scale vertical carry to
0.5–0.8 so jumps do not overshoot ceilings. Document per-platform carry
multipliers in level data. Pair with
coyote time
on platform edges so late jumps still inherit velocity.
Edge friction and sliding
When a rider walks off the leading edge of a horizontal platform, they should leave with platform horizontal velocity until airborne friction applies. Missing this produces the Harbor Foundry bug: players walked off a shuttle at zero horizontal speed and missed the next platform. Add a one-frame “was grounded on moving surface” flag for velocity merge on leave-ground events.
Path motion, scheduling and elevator logic
Waypoint paths
Define ordered waypoints with segment duration or speed, easing curves (ease-in-out for elevators, linear for factory belts), and per-node wait times. Ping-pong vs one-shot vs loop modes should be explicit enums in level data.
Trigger-driven platforms
Pressure plates, proximity zones, or story flags start/stop paths. Debounce triggers so rapid on-off does not reverse mid-segment unless designed. Show anticipation animation (lights, rumble) 300–500 ms before motion starts so players can board intentionally.
Synchronized chains
Multi-platform puzzles need a single timeline or phase clock. Harbor Foundry’s
three elevators shared a shaft_phase integer; each platform’s
offset was a function of phase, eliminating drift that had desynced independent
timers by up to 2.4 tiles over a 90-second loop.
Call buttons and priority
Player-facing elevators need state machines: idle at floor, moving, doors open, blocked. Queue requests; do not reverse direction instantly if a rider is still on the platform. Timeout doors so players cannot soft-lock inside.
Collision coupling: one-way tiles, crushers and drop-through
Moving platforms frequently pair with one-way collision so players can jump up through them and land on top. When the platform moves downward, temporarily disable one-way pass-through for riders already on top (they should stay glued). When moving upward into a player below, either push the player up or treat it as crush damage — pick one rule and apply consistently.
Crush volumes
Crushers between a moving platform and a ceiling must compare relative velocity,
not static overlap. If the platform rises into a ceiling while the player stands
on it, damage should trigger only when the gap closes below the player’s
hurtbox height and relative closing speed exceeds a threshold. Harbor
Foundry added crush_enabled only when the platform state was
Descending and the ceiling crusher was armed — eliminating
false positives during ascent.
Drop-through while riding
If down+jump drop-through is allowed, unparent the rider, zero vertical platform carry for one frame, and enable a short ignore-collision window with the platform layer. Without the ignore window, the player immediately re-grounds on the same surface.
Networked and deterministic moving platforms
In rollback or lockstep multiplayer, platform position must be a deterministic
function of frame number and seed, not server transform replication alone.
Authoritative sim advances platform_pos = f(tick); clients render
interpolated positions. Riders apply the same delta on the same tick. If player
input includes jump, inherit platform velocity from the sim tick, not from
interpolated render pose — otherwise jump carry desyncs by one frame and
causes rollback mispredicts.
For co-op PvE, a lighter approach works: host simulates path; clients receive phase index and segment progress at 10–20 Hz and locally integrate riders. Validate rider distance from expected platform surface; teleport if cheat or packet loss exceeds two tiles.
Harbor Foundry shaft refactor (case study)
Before: Three independent Tween elevators, transform
parenting, no velocity on walk-off, crushers using raw overlap tests. Metrics:
38% shaft completion, 22% of deaths flagged “unfair” in exit survey.
Changes:
- Unified
shaft_phasetimeline for all three platforms. - Switched to delta-position rider move in fixed tick; unparent on jump edge.
- Horizontal carry 1.0, vertical carry 0.65 on jump-off; walk-off inherits horizontal only.
- Crush damage gated on descending + armed ceiling state; 200 ms telegraph rumble.
- Boarding cue: floor light pulses 400 ms before departure.
- Widened second platform landing by 0.25 tiles after telemetry showed near-miss cluster.
After: 81% completion, unfair-death reports down 74%, median retry count per player dropped from 4.1 to 1.6. Level design change (wider landing) contributed an estimated 8 points; code fixes contributed the rest.
Technique decision table
| Goal | Prefer | Avoid |
|---|---|---|
| Deterministic factory/gauntlet elevators | Kinematic path + phase clock + delta rider move | Independent tweens per platform |
| Fair jump between shuttles | Velocity inheritance + coyote on platform edge | Zero carry on dismount |
| Vertical variety without new code | Bounce pads for launches; moving platforms for timing puzzles | Using elevators where a static jump arc suffices |
| Organic wobble (seesaw, boat deck) | Physics motor with capped forces + manual rider velocity | Pure parenting on dynamic bodies |
| Crush hazard readability | Relative velocity crush + state-gated damage + telegraph | Static overlap crush on moving geometry |
| Netplay platform puzzles | f(tick) path function + sim-tick carry |
Replicated transform lerp for gameplay logic |
| Teaching a new traversal verb | Single slow platform, clear wait, safe floor | Three-platform chain as first introduction |
Pitfalls
- Update vs FixedUpdate split — platform and character must integrate on the same tick; split causes elevator jitter.
- Parenting without jump unparent — player stays child while drop-through falling; always unparent on jump input.
- Ignoring walk-off carry — walking off the edge needs horizontal platform velocity merged into player velocity.
- Independent platform timers — chains drift; use one phase clock or master timeline.
- Crush without relative motion — overlap alone kills during benign contact; gate on closing speed and platform state.
- One-way pass-through during descent — riders fall through the surface they stand on; disable pass-through for grounded riders.
- Rotating platforms + euler lock — parenting to spinning discs gimbal-locks camera; prefer delta rotation on rider offset.
- No boarding telegraph — sudden departure feels cheap; add light, SFX, or shake before motion.
- Soft-lock in elevator — doors close with player inside and no exit; timeout open or crush override required.
Production checklist
- Pick kinematic path sim unless physics reaction is a core verb.
- Integrate platform motion in the same fixed tick as the character controller.
- Track grounded riders via collision contacts, not triggers alone.
- Apply delta position each frame; unparent on jump edge, not on airborne.
- Merge platform velocity into player velocity on jump and walk-off.
- Expose per-platform horizontal and vertical carry multipliers in level data.
- Define path modes: loop, ping-pong, one-shot; document wait times per node.
- Synchronize multi-platform chains with a shared phase or timeline ID.
- Gate crushers on platform state, relative velocity, and player hurtbox height.
- Telegraph motion 300–500 ms before departure on player-facing elevators.
- Test drop-through, jump, dash, and knockback off each moving surface.
- Log near-miss landings (distance to ledge) in playtest telemetry.
- For netplay, derive platform pose from
f(tick); inherit carry on sim tick. - Regression-test with frame-step debug overlay showing platform and rider velocity vectors.
Key takeaways
- Moving platforms are reference-frame problems — position delta and velocity inheritance matter more than mesh animation.
- Kinematic paths with a shared phase clock beat independent tweens for multi-platform puzzles.
- Walk-off and jump-off both need carry — Harbor Foundry’s miss rate was mostly zero horizontal speed on dismount.
- Crush hazards must use relative motion and state gates — static overlap on moving geometry reads as broken collision.
- Pair with coyote time and one-way rules from your broader platformer feel toolkit for a coherent vertical level.
Related reading
- Platformer design explained — level pacing, teaching order, and genre feel baselines
- One-way platform and drop-through systems — soft collision from below and down+jump routing
- Jump arc and gravity systems — impulse, gravity scales, and apex tuning on moving ground
- Coyote time and jump grace — edge leniency when jumping between shuttles