setLinearVelocity is not accurate

I’m using player.physicsImpostor.setLinearVelocity() to move the player in my scene, but it is not accurate. Sometimes it works correctly, but if the look direction in the x or the z axis is something like 0.9321339726448059, then it doesn’t move accurately. I tried manually updating the position of the mesh, using player.position.addInPlace(vel), and the movement is accurate enough, but it allows the player to clip inside physics bodies. Is there any other way to move the player, or is there a way to manually change the position of the mesh while respecting other physics impostors?

playground - https://playground.babylonjs.com/#50EU7Y#1

@Cedric will have a look right after the break.

Hi @saathvik

What do you mean by ‘not accurately’ ? It’s excepted to have some delta between perfect mathematical solution and result by the physics engine. If the delta is < 10e-4 then it’s in the physics engine margin.

In the mean time, you can try to increase the physics engine resolution steps like this:

    scene.enablePhysics(new BABYLON.Vector3(0,-9.81),new BABYLON.CannonJSPlugin(true))
    scene.getPhysicsEngine().setTimeStep(1/60);
    scene.getPhysicsEngine().setSubTimeStep(1);

Some explanation here:

2 Likes

I think this video will show what I mean -

It’s on this playground

What’s weird is that applying forces seems to be much more accurate - https://playground.babylonjs.com/#Z99KDU#2

the oldVel value is not updated when ‘w’ is pressed. This gives weird results.
The issue is not accuracy but mixing old values with new direction.
Moreover, your vectors are not normalized and this can also give different results when camera direction is parallel to the ground vs when camera is toward the ground or the sky.
On a design note, you should use add force if you want inertia or setLinearVelocity to the direction you want (without mixing with old force) when you don’t want inertia.

Turns out that it’s the limitVel function that’s making the movement inaccurate. I wonder why? All it’s really doing is stopping the velocity from exceeding a certain limit.

I don’t want inertia. I want acceleration. It’s why I was using oldVel.add(fVec), but the problem with that is that it never stops accelerating, so I decided to try to clamp that vector, but for some reason it doesn’t work in the expected way

I would do it that way:
Each frame, get the current linear velocity, get its length and reset it as the normalized camera direction multiplied by (the previous linear velocity length + the delta length).
The delta length is the acceleration/deceleration scalar value. something <0 when the user is not pressing ‘w’ and >0 when it’s being pressed.
That way, you get pregressive acceleration and deceleration and always the direction pointed by the camera.
note: check the direction multiplication is always >0 or it will go backward when not pressing ‘w’

It’s working, thanks :smile:
Playground - https://playground.babylonjs.com/#Z99KDU#9

2 Likes

Something weird is happening though - https://playground.babylonjs.com/#Z99KDU#14
am at the platform the player lands on and click, and for some reason, the player can’t move anymore. Why? The only thing different in this case is that the platform isn’t visible, but the only part of the movement this should affect is the jumping

I can move and jump. do I have something to do to not move?

Forgot to save it, but never mind - I just overlooked a piece of code that would register if the ‘w’ key was pressed only if the player was on an object

1 Like