Skip to content

Fix frame-rate dependent camera rotation and zoom in CameraControls#8494

Merged
slimbuck merged 1 commit intoplaycanvas:mainfrom
slimbuck:input-dev
Mar 3, 2026
Merged

Fix frame-rate dependent camera rotation and zoom in CameraControls#8494
slimbuck merged 1 commit intoplaycanvas:mainfrom
slimbuck:input-dev

Conversation

@slimbuck
Copy link
Member

@slimbuck slimbuck commented Mar 3, 2026

Summary

  • Fix mouse/touch/wheel inputs being incorrectly scaled by dt, causing camera rotation and zoom to blow up during frame hitches
  • Clamp dt to 100ms as a safety net for rate-based inputs (keyboard/gamepad movement)

Details

CameraControls applied * 60 * dt multipliers uniformly to all input types, but there are two fundamentally different categories:

  • Rate-based inputs (keyboard, gamepad sticks, virtual joysticks) report a continuous value that must be integrated over time — multiplying by dt is correct.
  • Delta-based inputs (mouse movement, mouse wheel, touch swipe, pinch) report accumulated pixel/scroll deltas between frames — they already scale with time naturally, so multiplying by dt double-counts the time component.

At 60 FPS the * 60 * dt factor equals 1.0 so the bug was invisible, but at lower frame rates or during hitches the camera would massively overshoot. For example, a 1-second hitch would amplify mouse rotation by 60x.

The fix splits multipliers into rate-based (with dt) and delta-based (without dt), and applies the correct one at each usage site. Behavior at 60 FPS is identical.

@slimbuck slimbuck requested review from a team and Copilot March 3, 2026 13:39
@slimbuck slimbuck self-assigned this Mar 3, 2026
@slimbuck slimbuck merged commit bdfe9e6 into playcanvas:main Mar 3, 2026
8 of 10 checks passed
@slimbuck slimbuck deleted the input-dev branch March 3, 2026 13:43
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes frame-rate dependent scaling in CameraControls by separating rate-based inputs (which should integrate over dt) from delta-based inputs (which already represent per-frame deltas), preventing rotation/zoom blow-ups during frame hitches.

Changes:

  • Clamp dt to 100ms as a safeguard against extreme per-frame integration for rate-based inputs.
  • Split input scaling into rate-based multipliers (keyboard/gamepad/virtual joystick) vs delta-based multipliers (mouse/touch/wheel).
  • Update rotation/zoom application sites to use the appropriate multiplier type.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 705 to 707
update(dt) {
dt = Math.min(dt, 0.1);
const { keyCode } = KeyboardMouseSource;
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dt is clamped in-place and then passed through to this._controller.update(frame, dt), so this changes controller integration/damping (and focus transitions) during long frames, not just rate-based inputs. If the intent is only to cap keyboard/gamepad/joystick rates, consider using a separate rateDt = Math.min(dt, 0.1) for the rate-based multipliers while still passing the original dt into the controller, or update the PR description to explicitly call out the broader behavioral change.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants