playcanvas / playcanvas/engine
ThirdPersonController: support drag input, press-triggered jump and pause/resume
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 16.8k
- Forks
- 2k
- Avg merge
- 4h 32m
- Merged PRs (30d)
- 222
Description
Problem
The Sunken Observatory example in https://github.com/playcanvas/web-components/pull/461 uses the Engine's ThirdPersonController, but needs a custom adapter for input and camera lifecycle behavior:
The adapter reaches into private fields of both ThirdPersonController and KeyboardMouseSource. Supporting these behaviors in the Engine would let the example use the stock controller declaratively and remove that dependency on implementation details.
Requested improvements
- Configurable pointer lock. The controller constructs
KeyboardMouseSource({ pointerLock: true }), although the input source already supports drag input. Expose a controller attribute so embedded experiences can select drag-to-orbit without replacing_desktopInput. - Jump on a fresh press. Desktop jump currently reads held Space state. Holding Space through landing triggers another jump. Support one jump per physical press, ignoring repeated keydowns. Preserve a quick press/release that occurs between input reads; the current key-state difference sampling can lose it. This should not change continuous movement-key behavior.
- Clear input on focus loss. Reset held keys, mouse buttons and pending pointer movement when focus is lost, so a missed keyup cannot leave movement stuck. The application should remain free to choose whether focus loss pauses gameplay.
- Supported pause/resume and view state. Inputs attach during initialization and detach on destruction. Provide a supported way to suspend/resume input and clear pending state without recreating the controller. Also expose initial yaw and a way to capture/restore orbit yaw, pitch, zoom and character heading for resets or recreation. Recovering yaw from the camera's Euler decomposition can flip the view after orbiting beyond a half turn; preserving the controller's continuous angles avoids this.
Verification scenarios
- Configure drag mode: orbit without acquiring pointer lock.
- Hold Space through a complete jump and landing: jump once; release and press again to jump again.
- Send Space down/up between two input reads: receive one jump press.
- Hold movement, switch windows, release there and return: no stuck movement or stale mouse delta.
- Orbit beyond 180 degrees, pause/resume, and repeat: preserve the view and heading, with no accumulated input or duplicate listeners.
The existing example adapter addresses these needs, but the API shape above is a proposal rather than a request to copy its implementation. Pointer-lock, held-jump and destroy-only input lifecycle behavior were also checked against the current Engine default-branch controller source.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked examples/assets/scripts/observatory-controller.mjs adapter and compare it with the current ThirdPersonController and KeyboardMouseSource behavior. Trace input initialization, jump sampling, focus loss, pause/resume, and orbit state against the five verification scenarios. Done means the stock controller supports the requested configuration and lifecycle behavior without the adapter's private-field access.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- game-dev
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100