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
37.1k stars 7.09k forks source link

[3.17] Arcade Physics tied to framerate, physics timescale has no effect, world collission issues #4529

Closed ampled closed 5 years ago

ampled commented 5 years ago

Version

Description

I'm having a set of different issues with Arcade Physics when upgrading from 3.16 to 3.17. I discussed some of these with @Antriel on discord and we agreed I should submit a github issue with a minimal repro. I'm not sure the repro covers all the issues I'm having, but it certainly demonstrates that there's some issues.

1) Setting worldFPS either via setWorldFPS or providing an fps value in the physics config affects game logic. This didn't happen in 3.16. In 3.17, setting the world FPS lower makes everything happen faster. This is demonstrated in the minimal repro.

2) Physics "happen faster" when I'm running my game in chrome on a screen with a higher refresh rate. I've tested my game on my stationary computer with a 144hz refresh rate and a laptop with a "regular" 60hz refresh rate. I've also confirmed these framerates by checking the game.loop.actualFps value. This is super problematic since you can't cap web browser framerates. This can be tested with any Phaser game on a 144hz monitor by switching between Chrome and Edge, since Edge's framerate seems to be capped at around 70 fps.

3) Setting the arcade physics world FPS to a high value (120+ in my case) makes the physics buggy. At stand still, a game object with gravity applied standing firm on a colission-enabled tilemap layer sends multiple different tiles to the colliders process callback, when at default worldFPS (or even at high worldFPS in 3.16) the process callback only receives the one and same tile over and over. It seems that the high worldFps completely breaks "consistent" frame to frame GameObject/Tilemap-Layer colission.

4) Setting the physics timescale doesn't seem to have any effect anymore

All of these things worked fine in 3.16. If needed I will provide more code examples, but generally most existing examples can be "broken" by setting the fps value in the physics config.

Example Test Code

https://stackblitz.com/edit/phaser3-typescript - 3.17 https://stackblitz.com/edit/phaser3-arcade-physics-world-fps-316 - same repro in 3.16

Additional Information

ampled commented 5 years ago

The 3.16 repro suddenly had some issues, I'm just posting these gifs demonstrating the issues if the repros go down.

3.16

Physics are more or less the same at both worldFPS settings, only "choppier" at 30 FUeVUMgKNp 5e6wUyyyBW

3.17

8uFThQPJ9s (the 30 worldfps seems to simulate physics faster. also notice how timescale changing doesn't affect anything)

TUqHnUlfkS Tilemap collission issues on high worldFPS. the gameobject is constantly being "pushed" down in spite of being in constant contact with the tilemap.

peteroravec commented 5 years ago

Same issue here... tried various settings in config but with no luck

ampled commented 5 years ago

I've tested more by running the 3.17 repro in a Chrome browser and moving the browser between a 144hz monitor and a 60hz monitor on the same computer. It definitively "runs faster" the higher the framerate is.

samme commented 5 years ago

In v3.17.0 Phaser always makes at least 1 physics step per game update (animation frame). That will make physics run "too fast" for any physics rate smaller than the animation rate. But any physics rate at least as large as the animation rate runs at the correct speed.

photonstorm commented 5 years ago

This is one of those non-trivial issues. I could revert it to how 3.16 worked, but it was changed for a good reason (i.e. you'd frequently get Bodies that were flag cleared but not updated), so it needs more carefully thinking about rather than simply putting it back how it was.

ampled commented 5 years ago

I'm sure the update fixed some issues, though I'm not sure what flag cleared means.

Some questions:

Could the old arcade physics be opt-in in the next release while these issues are being worked on? It's the only thing keeping me from upgrading my project to 3.17 right now and I'd love to get the controller input fixes.

Antriel commented 5 years ago

If anyone cares about my opinion:

photonstorm commented 5 years ago

Arcade Physics, by its very nature, cannot be decoupled from rendering. In all other physics systems, the sprite position is based on the body. If the body doesn't move (because no physics step took place that frame), then the sprite doesn't move.

AP literally works the other way around. The body position is based on the sprite position and, more importantly, the body delta is based on the current and previous sprite position. The body position is then modified based on velocity, collision, etc and fed back into the sprite at the end of the process.

There is nothing stopping the sprite from being moved of its own accord outside of physics (tweens, input, paths, etc) and this happens frequently. If a sprite was attached to a pointer move event, for example, it's absolutely possible for it to be in a completely different position to its body if the physics step is running at a lower rate than the frame rate. The bigger the difference between the two, the larger the gap between the visual and where the body actually is. This doesn't matter terribly, the bigger issue is the larger the difference, the larger the delta the body uses. It's a fundamental design flaw in the Flixel physics system but it's been that way since day 1 and the whole API is based around this reversed state of authority.

In an ideal world, if a sprite is enabled for physics, then nothing should change its position other than the body moving, at which point it doesn't matter if you step at 10fps or 200fps. Honestly, I long for that day, but it isn't happening yet. In the meantime, I'll address the step-every-frame issue.

photonstorm commented 5 years ago

Thank you for submitting this issue. We have fixed this and the fix has been pushed to the master branch. It will be part of the next release. If you get time to build and test it for yourself we would appreciate that.