phaserjs / phaser

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
https://phaser.io
MIT License
36.94k stars 7.08k forks source link

Physics framerate independence #3957

Closed okaybenji closed 6 years ago

okaybenji commented 6 years ago

When the game's frame rate drops, the physics slow down as well (at least with Matter.js, but I would imagine with other physics engines as well).

Ideally, an entity's inertia would not be affected by the performance of the machine running the game. (For instance, a ship moving 100px/sec at 60 FPS should not move 50px/sec at 30 FPS. They should travel at the same speed, and at 30 FPS they should go twice as far each frame as at 60.)

Please either add a configuration option to enable frame rate independence (by internally passing delta time to the physics engine), or simply do so always if that makes more sense.

Thanks very much!

Demo of current frame-rate dependence: https://streamable.com/z6sbf I run the simulation 3 times at normal speed, and then 3 times with 6x CPU throttling.

You can run this yourself here: https://codepen.io/anon/pen/KxKqOL

It is based on this Phaser 3 example, but I have simply added more bodies: https://labs.phaser.io/edit.html?src=src/physics/matterjs/body%20velocity.js

hexus commented 6 years ago

Frame rate independence for MatterJS was the default before Phaser 3.4.0, but it caused a lot of instability when used with Phaser's delta.

However, you can still provide your own function to step Matter's physics simulation. It's mentioned here in the change log:

https://github.com/photonstorm/phaser/blob/0eef6f1bb9a9cf3c12b162dd28f8afd080ea172f/CHANGELOG.md#version-340---miyako---12th-april-2018

If you find a good way to retain frame rate independence and stability with Matter in Phaser 3, please let me know! I'd be very interested to see it working. :)

okcompewter commented 6 years ago

I've noticed this using Arcade physics as well: on slower performing machines, character movement is also slowed. Not great for a real-time multiplayer game. Is it possible to address this while using Arcade physics?

hexus commented 6 years ago

I'm not certain when it comes to Arcade. That's always been stepped a fixed amount as far as I'm aware.

By the way, when I run your code pen, the bodies tumble at and angle and start flying everywhere, and eventually the browser tab crashes! :smile:

photonstorm commented 6 years ago

Arcade Physics was changed in 3.10 to purposely use a fixed time-step, ensuring the results are deterministic (which is far more important for a multiplayer game):

Both Matter and AP allow you to change how the simulation steps to match your requirements to whatever is needed. Matter before using a fixed time-step was a mess (try it and see for yourself), so there's no way it's going to change back again. Define your own step for full control.

okaybenji commented 6 years ago

Deterministic results on the client are not more important for multiplayer games than a physics system's frame rate independence. In most real-time games the determinism should be on the server, not the client.

@photonstorm Can you explain what you mean by "Define your own step for full control"? Do you mean write our own physics simulation? @hexus Would you mind telling me more about the instability you're talking about?

hexus commented 6 years ago

@okaybenji Any considerable hitches in performance between frames would cause a delta too large for Matter to handle in a stable way, causing bodies to start flying across the world with huge velocities from the lightest impulses.

Your code pen demonstrates this on my machine. I'll try to record a GIF.

okaybenji commented 6 years ago

Ah, okay I see that. Thanks very much for the help!

hexus commented 6 years ago

manycam3

okaybenji commented 6 years ago

I wanted to point out one weird thing with this. I accidentally left the block from the original demo in place. (This line: var block = this.matter.add.image(400, 100, 'block');) If you take it out, the update method never gets called:

https://codepen.io/anon/pen/LJExXG

Should I open an issue for this?

hexus commented 6 years ago

If you check the console, you'll see that block is not defined.

Commenting out these lines gets your example running again, with the same issues:

block.setFriction(0.05);
block.setFrictionAir(0.0005);
block.setBounce(0.9);
okaybenji commented 6 years ago

Ah, of course! 😅 Sorry about that. Thanks again for your help.

bulboka commented 5 years ago

Matter.js Body.update seems very strange to me.

The velocity is not multiplied by deltaTime, when changing the position. The force is multiplied by deltaTime squared (why squared?), though it is reset to zero every frame after update. So strictly speaking it's not a force but something like an impulse and there's no reason to multiply it by time.

Maybe all of it was done in the name of performance optimization or for some other reasons, but the point is that Matter.js is not framerate independent in any way, no matter what timeDelta you're passing to it.

photonstorm commented 5 years ago

@bulboka you need to mention this on the Matter.js repo, it's outside of our control.

nfernand commented 5 years ago

I am currently stuggling with similar issues. I have users who use a 144Hz monitor causing requestAnimationFrame() to be called more than once every 16ms or so. With matter using fixed timestep, the simulation runs way too fast for those users and also runs too slow when throttling cpu for simulating slower computers.

I have also tried using custom timestep based on elapsed time since last frame broke down into smaller steps to avoid beforementioned issues if elapsed time is too big. But as already discussed here, using matter without fixed timestep indeed is messy and I could not get results to be smooth and predictable using this technique.

Anyone has any advice for me if I want to use a physics engine combined with phaser 3 that manages polygonal bodies and also support 144Hz monitors ? I feel a bit stuck here.

okaybenji commented 5 years ago

We fell back to using P2 with Phaser 3 instead of Matter... there are still some issues with 144Hz monitors even with P2, but it's better.

epurban commented 4 months ago

Can't believe this is still an issue.

photonstorm commented 4 months ago

Can't believe this is still an issue.

Feel free to take it up on the matter repo. It's still not resolved there.