fix: reset double jump when impulse up is applied - #9510
Conversation
|
Windows and Mac build successful in Unity Cloud! You can find a link to the downloadable artifact below. |
|
Tests: 24500 passed, 0 failed ✅ |
…y-impule' into fix/movement/double-jump-reset-by-impule
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
✅ Approved
QA'd on Windows and Mac.
Tested:
- Shroomzoom.dcl.eth — verified mushrooms correctly reset double jump on landing (aware of the known scene-side edge cases noted in the description regarding missing colliders / trigger area mismatches).
- Genesis Plaza (umbrellas/trampolines) — double jump resets correctly after impulse.
- Sky Chaser — double jump and gliding work as expected.
- Pigeon Deluxe — double jump and gliding work as expected.
Also did a basic smoke test on regular jumping (non-impulse) to confirm no regressions there.
9510.mp4
✅Smoke test performed:
- ✔️ Backpack and wearables in world
- ✔️ Emotes in world and in backpack
- ✔️ Teleport with map/coordinates/Jump In
- ✔️ Camera
- ✔️ Skybox
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…y-impule' into fix/movement/double-jump-reset-by-impule
This comment has been minimized.
This comment has been minimized.
pravusjif
left a comment
There was a problem hiding this comment.
LGTM, this should only be affecting the reset of the jump counts when there is an external impulse involved, according to the code changes.
|
Claude finished @popuz's task in 1m 52s —— View job Security & Dependency Review — re-run on
|
| # | Severity | Concern | Location |
|---|---|---|---|
| 1 | MEDIUM | A suite whose artifact never uploads still renders green. [ -f "$file" ] || continue skips that mode and status stays passed. The new hasResults check only covers "ran but produced no XML" — a runner death before the upload step still slips through. Partly self-evident to a human (the table renders one row instead of two), so the practical impact is lower than the label suggests. Drive the mode list off steps.download-*.outcome. |
pr-comment-test-failures.yml:86 |
| 2 | MEDIUM | Six tag-pinned third-party actions in jobs holding pull-requests: write (W.7b, pre-existing on dev). SHA-pin when convenient. |
pr-comment-test-failures.yml:43,54,150,159 + warnings file |
| 3 | LOW | set -euo pipefail + a jq type error on a fork-controlled artifact aborts the step and suppresses the comment. Fails closed. |
pr-comment-test-failures.yml:104,111 |
| 4 | LOW | Single-line markdown injection via fork-controlled test names / file paths — gsub("[\r\n]"; " ") is applied to .message but not .file. Spoofing/cosmetic only. |
pr-comment-test-failures.yml:111, pr-comment-warnings.yml:191 |
| 5 | LOW | GroundDistance's struct default of 0f satisfies <= 1f, so an upward impulse arriving before GroundDistanceSystem first runs reads as "on the ground" (MAX_GROUND_DISTANCE = 1000 is the real sentinel). ApplyGliding.cs:24 uses the opposite comparison, so the same 0f is fail-safe there and fail-permissive here. Worst case is one extra air jump on the first frame. |
ApplyExternalImpulse.cs:28 |
Withdrawing L2 from my last review (droppable jq failing the lint job): .rule is built as (.ruleId // ""), so it is always a string by the time test() sees it, and the step pre-seeds echo '[]' > droppable.json. The failure path I described isn't reachable. L3 (droppable pointing devs at unrelated files) stands as a process question for a human, not a security one.
W.1/W.3/W.4/W.5/W.6/W.9 remain N/A (no LLM in any of these comment-posters; nothing reviews or executes PR content), W.2 mitigated by the random EOF_$(uuidgen) delimiter, W.8 N/A (workflow_run only, no pull_request_target, no checkout of PR code), W.10 fine (explicit contents: read + pull-requests: write).
Summary
| Item | Version | Source | Type | Scope | Risk | Confidence |
|---|---|---|---|---|---|---|
| (no dependency changes) | — | — | — | — | — | — |
pr-comment-warnings.yml (need=$(( ))) |
n/a | this PR | workflow | CI, base context | HIGH | |
pr-comment-test-failures.yml (false-green) |
n/a | earlier in PR | workflow | CI, base context | MEDIUM | HIGH |
Tag-pinned actions in pull-requests: write jobs |
n/a | pre-existing | workflow | CI, base context | MEDIUM | HIGH |
ApplyExternalImpulse.cs (GroundDistance default) |
n/a | earlier in PR | source | ships to client | LOW | HIGH |
No blockers left. The remaining MEDIUMs are CI-integrity/hardening items, one of which predates this PR; neither reaches secrets or repo write, so they're reasonable to land as follow-ups rather than gate this fix.
Separately, on @pravusjif's question about the workflow files — factually, none of the four workflow changes relate to the double-jump fix: pr-comment-artifact-url.yml is a logo swap, and the other three add the droppable warning list, the "remove at least N warnings" message, the crashed-suite hasResults state, and now this sanitization. That's a maintainer call on scope, not a security one.
DEPENDENCY_REVIEW: NEEDS_ATTENTION
· Branch

Pull Request Description
What does this PR change?
Fixes the double jump sometimes not resetting in SDK scenes with jump pads (platforms that push the player up when touched).
Root cause — a race between the scene tick and our physics tick.
JumpState.JumpCountis reset in exactly one place (ApplyJump), and only when a FixedUpdate tick observesCharacterRigidTransform.IsGrounded == true. ButIsGroundedis produced later, inInterpolateCharacterSystem(Presentation loop), fromCharacterController.Movecollision flags. A scene detects the touch on its own tick and sends an upward impulse (PBPhysicsCombinedImpulse→SDKExternalPhysicsSystems→ApplyExternalImpulse), which can launch the character before any fixed tick ever sees a grounded state — the physical contact never registers, the reset never fires, and the airborne clamp keepsJumpCount ≥ 1. The player then has to wait for the next real landing to get the double jump back.Fix.
ApplyExternalImpulse.Executenow receivesref JumpState: an upward impulse consumed whileIsGroundedor within1 mof the ground (GroundDistance, already computed every frame byGroundDistanceSystem) is treated as a landing and resetsJumpCountand any pendingAirJumpDelay. An upward impulse taken clear of the ground is not a landing and does not restore air jumps; horizontal and downward impulses are unaffected.Covered by unit tests:
ApplyExternalImpulseShould.Test Instructions
Play shroomzoom.dcl..eth and verify that each mushroom resets your double jump.
BE AWARE:
Do basic smoke test on jumping and impulse combinations.
Additional Testing Notes
Quality Checklist