decentraland / decentraland/godot-explorer

Locomotion Iteration #1: Speed, Acceleration & Air Behavior v Unity

Open
#2,850 0 comments 0 reactions 1 assignee Claimed by @manuelmaceira View on GitHub
controls enhancement feature parity locomotion-pass-1 mobile
Dominant language
Rust
Stars
18
Forks
19
Avg merge
4d 2h
Merged PRs (30d)
43

Description

## **⚠️ Problem:**
Godot assigns locomotion velocity directly — no acceleration, no air drag, full air control — so the avatar starts, stops and turns instantly where Unity carries weight. Movement reads "on rails" against the desktop client. Drives **Playtime**.

## **🏁 Scope:**
Speed constants, acceleration/deceleration curves, air control and air drag in `player.gd`. Jump arc and gravity stay in #1557. Slope speed modifier stays in Iteration 2.

## **📝 Deliverables:**
- [ ] Run speed 11 → 10; walk 1.5 and jog 8 confirmed unchanged
- [ ] Ground acceleration 20 → 25 over a 0.5 s curve
- [ ] Air acceleration 15 → 20 over a 0.5 s curve
- [ ] Deceleration dt-scaled — stopping distance independent of physics tick rate (B4)
- [ ] Quadratic horizontal air drag, coefficient 0.2
- [ ] Air control reduced vs grounded — air accel pair + MoveTowards, not full ground parity
- [ ] Start / stop / turn captured side-by-side vs desktop on test scene `-98,103`
- [ ] Stopping distance verified constant under forced frame drops

## Metrics
Playtime. No instrumented baseline for movement feel — measure via the #905 reproduction checklist (B4: release keys at full run under frame drops; Unity stops consistently, Godot varies with tick rate).

## Findings

| | Godot `main` | Unity |
|---|---|---|
| Walk / jog / run | 1.5 / 8 / 11 | 1.5 / 8 / 10 |
| Acceleration | none — velocity assigned directly (`player.gd:513-514`) | ground 20 → 25, air 15 → 20, 0.5 s curve (`ApplyCharacterMovementVelocity.cs:72-78`) |
| Deceleration | `move_toward(v, 0, walk_speed)` per tick, not dt-scaled ⇒ 90 m/s² at 60 Hz (`player.gd:520-521`) | SmoothDamp, `StopTimeSec = 0` ⇒ instant |
| Air drag | none on locomotion velocity | quadratic, 0.05 × 4 = 0.2 (`ApplyHorizontalAirDrag.cs`) |
| Air control | full, identical to grounded | reduced — air accel pair + MoveTowards |

B4 is a latent bug, not a tuning gap: the deceleration step is per-tick, not per-second. Correct at a stable 60 Hz, wrong under load — which is where mobile lives.

**Replicate behavior, not asset values.** Dead on the Unity side: `StopTimeSec = 0` (degenerate SmoothDamp = instant stop), `GroundDrag`, and the whole `ApplyAirDrag.cs` file — the live one is `ApplyHorizontalAirDrag.cs`.

D1 resolved: run 10, matching Unity. The reachable-geometry set changes with it — scenes are authored against desktop reachability.

## **🔗 References:**
- [`ApplyCharacterMovementVelocity.cs`](https://github.com/decentraland/unity-explorer/blob/dev/Explorer/Assets/DCL/Character/CharacterMotion/Velocity/ApplyCharacterMovementVelocity.cs) — the acceleration pair and 0.5 s curve to port
- [`ApplyHorizontalAirDrag.cs`](https://github.com/decentraland/unity-explorer/blob/dev/Explorer/Assets/DCL/Character/CharacterMotion/Velocity/ApplyHorizontalAirDrag.cs) — live air drag; `ApplyAirDrag.cs` beside it is dead, do not port
- [#905](https://github.com/decentraland/godot-explorer/issues/905) — parent audit, §3.4
- [#943](https://github.com/decentraland/godot-explorer/pull/943) — closed unmerged; its body is an ADR-grade locomotion spec, reusable as the implementation checklist
- [#2753](https://github.com/decentraland/godot-explorer/issues/2753) — capsule fix; land it first, speed changes read differently on a capsule that reaches the ground

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.