Sprite.update(t,dt) is not consistent. Position of sprites doesn't change smoothly

The velocity of the sprite is set to 120 using .setVelocityX(120)
and I am also calling the update() of the object manually with hardcoded values like obj.update(0,16) from the scene’s update()
The obj extents Phaser.Physics.Arcade.Sprite and inside its update function I am printing its position as follows

    update(t:number, dt:number) {
        super.update(t, dt)
        console.log('x:',this.body.x,t,dt)
        this.setVelocityX(120) 
    }

Now I expect x coordinate to increase linearly on every update but this isn’t the case

Box: velocity: 0 0 16
main.js:113 x: 1.92 0 16
main.js:113 x: 3.8400000000000016 0 16
main.js:113 x: 5.760000000000003 0 16
main.js:113 x: 7.680000000000005 0 16
main.js:113 x: 9.600000000000007 0 16
main.js:113 x: 11.520000000000008 0 16
main.js:113 x: 11.52000000000001 0 16
main.js:113 x: 13.44000000000001 0 16
main.js:113 x: 15.360000000000012 0 16
main.js:113 x: 17.280000000000015 0 16
main.js:113 x: 19.200000000000017 0 16
main.js:113 x: 21.12000000000002 0 16
main.js:113 x: 23.04000000000002 0 16
main.js:113 x: 23.04000000000002 0 16
main.js:113 x: 24.960000000000022 0 16
main.js:113 x: 26.880000000000024 0 16
main.js:113 x: 28.800000000000026 0 16
main.js:113 x: 30.720000000000027 0 16

Though at the beginning it increments by 1.92 (as 1.92x1000/16 = 120) but then it sometimes skips an update or updates twice. (ie increments by 1.92x2).

I event tried this.physics.world.setFPS(1000/16) in the scene but no use.

My current project demands the physics simulation to be exact every time I run it. To be clear, I am doing a sort of physics simulation. The first case is a body moving through space at a constant velocity.
And given a dt = 16ms the simulation will ultimately produce positions, velocity etc of each particle for each time step (dt) and I should produce the same output on every run.(not only after 1s but on very dt step).

The physics simulation steps are independent of the frequency at which scene update is called.
If you run this at anything other than 60Hz, you’ll see a lot more ‘inconsistency’.
So you shouldn’t be expecting x to increase on every scene update. You could check after a second where x is, that would make more sense.

Also, you’re not using t or dt (unless you’ve overwritten Sprite.update?), so there’s no need for any of this. You should do setVelocity only once.

Yes I have override the sprite’s update method. The update function snippet it showed above is from the sprite class.
I want the physic simulation to be same given the same innitial condition and a fixed ‘td’, the runs should produce the same output.
How to achieve this?

No it’s not. A Sprite knows nothing about setVelocity. So this is a Physics Sprite.

You have achieved this. Your logging is just wrong.

You have achieved this. Your logging is just wrong.
Can you explain how to log?

to be on the same page here is more code

class Box extends Phaser.Physics.Arcade.Sprite {
    private boxtype:BoxType

    constructor(scene: dSyncedScene, x:number, y:number, boxType:BoxType) {
        super(scene, x, y, BoxType[boxType].toLowerCase())
        scene.physics.add.existing(this); // needed otherwise this.body is null
        this.setOrigin(0.5, 0.5)
        this.setDepth(10)
        this.boxtype = boxType
        // this.setVelocityX(constants.BOX.VELOCITY)
    }
    update(t:number, dt:number) {//overridded
        super.update(t, dt)
        console.log('Box: x:',this.body.x,t,dt)
        this.setVelocityX(constants.BOX.VELOCITY) 
    }
}

in scene update() function:

    update(t, dt) {
        ....
        this.phuObjs.forEach(obj => {
            obj.update(0, 16)
        })
        ....
    }

Please read my original response again. You’re not overriding Sprite.
Join me (Milton#6285) on discord if you want to chat.

I think what you’re seeing is normal.

The physics world steps at a fixed size, 16.66ms.

The game loop steps at a nonfixed size, averaging 16.66ms on most devices, but with some variance. So usually there is one physics step per scene update, but sometimes two and sometimes zero.

The physics step happens through the Arcade Physics plugin, not through the game object’s update() method.

@Milton and @samme thanks for all the help.
I was thinking the game object’s update() method was doing the physics calculations and that was causing all the confusion. So as pointed out by Milton the logging is wrong.
So logging is done inside this callback then the output is correct.
scene.physics.world.on('worldstep', function(delta) { /* ... */ }, this);

If my understanding is correct I can tie the physics update step with the scene update using the below code:

this.physics.world.setFPS(1000/16)
this.physics.disableUpdate()

And inside scene’s update()
this.physics.world.step(16/1000)
Then that too should make the logging consistent?

Update: using the above way the logging is consistent on every run but the physics calculations seems to be messed up.
So what’s the correct way to tie the physics and scene update loops?

Why would you want to do that? Scene delta (game framerate) isn’t constant. So if you then use a constant step (16/1000), your physics get messed up.
If you step yourself, you should step(delta). But that’s not deterministic of course…

My guess is you don’t want to tie the physics and scene updates. Do everything that depends on the physics step inside the worldstep callback, and anything that doesn’t inside update().

@samme @Milton
I think the this.physics.world.on('worldstep', function callback(delta) { ... } is still not perfect.

Cause I found a run with a body under uniform velocity as follows,

x    step
25      1
26      2
27      3
27      4 *
29      5
30      6

My hypothesis: It can happen that the callback is called before the “worldstep” execution is complete. (Like the callback gets executed in between the physics calculation before x is updated).

The step execution is complete, but that doesn’t mean the body position is updated.

See the Body update code:

//  Now the update will throw collision checks at the Body
//  And finally we'll integrate the new position back to the Sprite in postUpdate

postUpdate is the one that actually updates the position, and that comes after the worldstep event.You would need an event after world.postUpdate.

there is no event firing from [world.postUpdate](phaser/World.js at v3.51.0 · photonstorm/phaser · GitHub)

Also, I think the problem is with the use of callback. If using call back there is no guarantee when the js engine will execute it. For example,
this.physics.world.on('worldstep', function cb1(delta) { ... } cb1 can get executed immediately after worldstep or after world.postUpdate is completed or maybe even further in the future.

I never said there was, I said you would need it.

This is complete nonsense. It fires when called.
this.emit(Events.WORLD_STEP, delta); can be called by 4 functions, postUpdate is not one of them.