bevy_xpbd icon indicating copy to clipboard operation
bevy_xpbd copied to clipboard

Inconsistent Behavior with Velocity Calculations and Frame Rates in 2D Movement

Open JustKira opened this issue 1 year ago • 2 comments
trafficstars

Description:

I've encountered several strange behaviors while trying to implement top-down directional movement in my game using Bevy version 0.14.1 and Avian2D version 0.1.2. Here are the issues I faced:

  1. Linear Velocity Acting Strangely:
    I downloaded some 2D examples and ran both kinematic and dynamic examples. On my 240fps monitor, the game appeared to run slower compared to a 60fps monitor.

    • Observation: When I removed Time.deltaTime from the calculations, everything seemed to work correctly, which led me to assume that this adjustment would also apply to angular velocity.

    • Problem: However, for angular velocity, removing Time.deltaTime caused erratic behavior on different screens. When I added Time.deltaTime back, it worked as expected.

  2. Linear Velocity and Object Orientation:
    Another issue is with linear_velocity.x and linear_velocity.y not aligning with the object's orientation. I tried multiplying linear_velocity.x by transform.up().normalized(), which worked to some extent.

    • Observation: I noticed that the aircraft slows down when turning, as if it's losing speed while turning. This behavior was unexpected.

This issue is a follow-up to issue #498, but I decided to create a new issue due to the weird behavior related to linear_velocity and Time.deltaTime.

Steps to Reproduce:

  1. Use a high refresh rate monitor (e.g., 240fps).
  2. Run the 2D kinematic and dynamic examples in Bevy with Avian2D.
  3. Observe the difference in game speed at different frame rates.
  4. Modify the velocity calculations by removing or adding Time.deltaTime.

Expected Behavior:

  • The game should run consistently across different frame rates.
  • linear_velocity should respect the object's orientation without unexpected speed loss during turns.

Actual Behavior:

  • Game speed varies with frame rate.
  • Removing Time.deltaTime causes erratic angular velocity behavior.
  • The aircraft loses speed when turning.

Environment:

  • Monitor refresh rate: 240fps, 60fps
  • Bevy version: 0.14.1
  • Avian2D version: 0.1.2
  • Operating System: Ubuntu.22.0.4

Additional Context:

  • This issue might be related to how Time.deltaTime is being applied or calculated within the physics update.

Thank you for looking into this issue!

JustKira avatar Aug 25 '24 16:08 JustKira

I am seeing something similar when I run the dynamic_character_2d example. I found it quite easy to reproduce by turning VSync on and off like so:

DefaultPlugins.set(WindowPlugin {
    primary_window: Some({
        Window {
            // present_mode: bevy::window::PresentMode::AutoVsync,
            present_mode: bevy::window::PresentMode::AutoNoVsync,
            ..Default::default()
        }
    }),
    ..Default::default()
})

We can observe the issue with movement along the X axis, the Y axis is unaffected as it is not multiplied by the delta time.

cullenr avatar Jan 31 '25 16:01 cullenr

I downloaded some 2D examples and ran both kinematic and dynamic examples. On my 240fps monitor, the game appeared to run slower compared to a 60fps monitor.

I think the issue here is that in the dynamic and kinematic examples the apply_movement_damping system applies the same damping every frame regardless of the time between frames. I fixed it by doing something like linear_velocity.x *= 1.0 - damping_factor.0 * delta_time; Though I'm not sure you can technically still call it a damping factor in this case.

GitGhillie avatar Mar 22 '25 08:03 GitGhillie

linear_velocity.x *= 1.0 - damping_factor.0 * delta_time;

This is going to have bad behavior if delta_time gets large and the total factor goes negative. Looking at this https://theorangeduck.com/page/spring-roll-call. I think what you want is:

linear_velocity.x *= exp2(-delta_time * damping_factor.0)

edit: I guess you normally would use an approximation of the exponential, so this becomes: linear_velocity.x *= 1 / (1 + damping_factor.0 * delta_time);

hymm avatar Sep 18 '25 17:09 hymm