-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[3.x] 2D Fixed Timestep Interpolation #76252
Conversation
bd6c574
to
7b4f835
Compare
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Will need a rebase now hierarchical culling is merged, I'll do this when up and running again (but is still possible to look through now). It's a while since I wrote but one area I would like to improve (likely in a later PR) is the culling. At the moment this merges the previous and current AABB from each two adjacent ticks, with the anticipation that in most circumstances, the interpolated AABB will be between the two. However there may be exceptions with some rotations (particularly where pivots are involved), where the AABB moves outside the merged AABB, so I'm intending to look into this. If possible I would like to avoid recalculating the AABB on every frame - which would always be correct, but stress the calculations of the AABB and the hierarchical culling unnecessarily. Consider that running at e.g. 30tps and 300fps, we would be doing 10x as many of these calculations as necessary. |
I tested this PR locally with https://github.com/Calinou/platshoot/tree/physics-interpolation-test. The basic functionality works well, but I noticed a few issues – see the videos below.
Physics FPS is set to 20 in the project (lower values cause frequent player tunneling with the tiles). No interpolationsimplescreenrecorder-2023-07-03_12.53.20.mp4With interpolationsimplescreenrecorder-2023-07-03_12.53.49.mp4 |
I'll take a look, I didn't explicitly test the camera smoothing.
This is kind of expected, I spent quite a bit of time on the 3D interpolation rewriting the global particles (more than half the time I spent developing). I haven't touched the global 2D particles at all yet, working on the principle of having something working would be better than nothing at all to get users started. For global particles each particle needs to be interpolated individually if tick based, and a framework needs to be added to support this. (This is also incidentally the reason why I've been taking a while adding interpolation to 4.x, because particles is a bag of worms, and the implementation was in flux in master at the time). I'll have a look at the 2D particles and see if they can be fixed up in a similar manner to 3D, but it might make sense for a second PR (I'll make this clear in the PR description that particles are not yet converted). |
By the way, I ported another project if you need more ways to test it: https://github.com/Calinou/escape-space/tree/physics-interpolation-test |
I had a little look at the issue with the camera smoothing being slower with interpolation switched on. The reason is that in the "platshoot" demo project above, the camera process mode is set to I'm not currently sure whether it makes any sense to try and apply / support smoothing per frame with interpolation on. At best you would get some kind of double smoothed "blancmange". It is doable with some rather more complex logic, but I'm not sure it makes any sense. 🤔 I suspect the best way of fixing this (at least until we get further feedback / some ideas how this might be useable) is to just emulate the physics process mode when interpolation is switched on. We could add e.g. a Smoothing at idle when using interpolation would also likely cause stutters, because of the same reason in 3D we recommend Actually the way UPDATE: |
This comment was marked as resolved.
This comment was marked as resolved.
Indeed, I didn't make any manual changes (other than removing the smoothing add-on which both projects previously used, and changing the node structure accordingly). |
For the bullets, "platshoot" could potentially be improved with a little trick that I need to add to the docs for 3D:
Normally when adding a new object to the scene you add it and call In order to create a bullet "in flight":
This means the bullet is to some extent "ahead" of itself, but can make the visuals look nicer. The only thing is you need to be aware that the bullet will likely tunnel through anything it would have hit in that first tick, because as far as the physics is concerned, it is starting at "T+1". Another alternative is to hide the bullet for the first tick, but this can make the input feel laggy. |
I've tracked this down to being an order of operations bug. The problem was that the Changing the current / prev update to occur on UPDATE: Ok pushed with this fix. You will need to test the artifacts though rather than my fork as I haven't made builds yet with this change. |
I tested this PR on https://github.com/Calinou/platshoot/tree/physics-interpolation-test again, Camera2D smoothing now works well thanks to the automatic override (there's a warning printed). Particles are still not smoothed, but it may be better to leave this for a future PR so this can be merged in 3.6 betas. The player movement itself feels very smooth. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave the code and documentation a cursory look and it looks good to me.
I have CPUParticles2D working in local and global modes. But would prefer for separate PR because this involves some fundamental changes to how they work. Both 2D and 3D particles in global mode originally previously worked in somewhat strange way (I keep meaning to ask reduz why they work like this, but perhaps it he did not write them originally). They apply the inverse of the parent transform to get to global space, instead of simply marking the nodes as using identity transform. This worked before interpolation (although strange) but with interpolation, this technique is not mathematically good. So for 3D particles I shifted it to marking the node as having identity transform, and baking the global transform into the particles. For 2D particles, we probably need the same (indeed that is what I've done so far to get it working), but there is an added complication of y-sorting. So I might need to do some experiments here to check this particle system works with y-sorting. For GPU 2D Particles I have no idea yet. I didn't actually have to do anything special to get them to work in 3D, but they look like they need some tweaks to work with 2D. For 2D interpolation in 3.6 I'm envisaging we will need 2-3 PRs, plus possible extras for fixing regressions / problem areas as they come up. So just having the basic version in to start with would be good to get feedback as early as possible in betas. |
Camera is now perfectly following the player! Tested on 144hz monitor with physics fps set to 60 and it's perfectly smooth and responsive. Some other bugs I noticed:
|
I'll try and check these out but:
As with all physics interpolation, tweens will only work if done on the physics tick (there are similar instructions for 3D). I'm not super familiar with tweens, but I'd double check this is the case in your test. Note that when using an interpolated camera, shakes only have the resolution of the physics tick rate, so if you need to use more than this resolution you would need a manually interpolated camera. UPDATE:
I'll take a look. I had a similar problem with sprites changing direction, and the TransformInterpolator contains a special fix for these instantaneous flips. Maybe I'm not using this for the parallax layers. Outdated - see later in thread for solution.UPDATE: although `motion_offset` is interpolated, `motion_mirroring` does not appear to be an interpolated property. Ah, it seems to be set through a "back door" to the `VisualServer` in the function `canvas_set_item_mirroring()`. There are a large number of properties that inevitably _won't be directly supported_ by the core interpolation, we'll have to evaluate on a case by case basis whether they are worth adding direct support. For now these will need manual interpolation (or move in `_process()` rather than `_physics_process()`).To explain this rationale:In principle almost everything in the engine could be physics interpolated. Changing If there is popular demand for particular areas we can add in-built interpolation support on a case by case basis. But I think this will depend on feedback after a beta.
I'll take a look. It could be it needs a manual If you have MRPs for any of these it would be useful. 👍 Yes I think I'll need MRPs. I'm trying to reverse engineer the problems but the text is not enough to reproduce. |
I'm aware that everything like How to use:
Then try with physics interpolation turned off to see that it behaves differently. |
Ah much better with the MRPs. 👍 In fact now from the description I can work out what is probably going on with the offset, the logic in I suspect the parallax background is similar to a problem I had to fix when testing "jetpaca". Parallax backgrounds that perform a wraparound mod (e.g. from 0.99 -> 0) work fine without interpolation because you don't see the glitch. With interpolation, you sometimes get an interpolated frame at value e.g. 0.45. For "jetpaca" I simply turned off interpolation for these backgrounds as they were moved in BTW if you change physics tick rate to e.g. 5-10 tps (rather than 60 tps) you can see more clearly what is going on. It's always a good idea to do this when fixing interpolation issues. The toggle limits is doing exactly what we would expect with interpolation, it is gliding to the new location over a tick. If we want instantaneous movement with interpolation, we usually have to request it explicitly, with However in this particular case, the new location is controlled by the limits rather than the user calling e.g. |
That's the thing. As discussed, FTI is a physics mechanism which, when enabled, stirs everything to it in order to get things working properly. Almost no node in idle would work as expected, unless it is manually or automatically moved to physics (hence the delta in opinions about the configuration warning, among others). This is the shift in paradigm I have been struggling with when FTI is on. It's a real shift in thinking, because in Godot idle is the default processing mode for all nodes: cameras, tweens, particles, etc. Making all of these work with FTI automatically looks like mission impossible, unless, perhaps like the Camera2D, the whole branch under an FTI enabled node is cascaded and forced to physics... |
I now have a fairly simple fix for this in |
That did the trick for the mirroring.
|
Pan not working when camera not moving
Ok, this should now be fixed. Much as it irks me, I've mimicked the old behaviour, which actually has a bug. Like the old behaviour I'm now calling However, this means that (like the existing non-interpolated version), This means the smoothing code is applied once when the camera is not moving, and twice when it is. This is not mathematically correct (if we want to actually produce a smooth result). I've made a rather large TODO comment to point to this bug as it is something we should resolve at some point. Perhaps we can do it for non-interpolated camera too, but it will result in small change in smoothing behaviour. There are also potential for regressions fixing this in the regular camera. With interpolated camera we have carte blanche, there's no existing behaviour to break, so it would be nice to fix this in a PR before 3.6 stable. The correct fix will probably entail deferring the smoothing until either Parallax Layer ChuggingI've worked out what the problem was with the parallax layer .. they are being updated on every frame rather than every tick. This is driven by the This also means I can probably remove the fix for wraparound that I'd previously added to the parallax layer, as this shouldn't occur any more. Will push this fix soon. Limits snapping
Fixed. You were correctly calling All mentioned bugs should be fixed now I think, barring particles and the double update for smoothing (which need separate PRs). 👍 |
9a9b08b
to
68752c6
Compare
Just tried it and it's working good! One thing that should be made clear is when exactly to use
or
or
I got the best result by putting it in the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style review pass.
Adds support to canvas items and Camera2D.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passes style review.
Was well tested by @Calinou and @lawnjelly, so let's merge and see how it fares under wider testing.
Thanks! |
Adds support to canvas items, canvas lights, canvas light occluders and Camera2D.
Notes
get_global_transform_interpolated()
, probably leave for another PRInterpolationMode
as 3D, although there is significant different - interpolation is performed locally and passed down to children, rather than performed globally per node.TransformInterpolator
Controls
reset_physics_interpolation()
support as in 3Dcanvas_item_transform_physics_interpolation()
to allow origin shifting techniquesiteration_prepare()
for consistency with 2D. I think this should be okay, but if there are any regressions it's easy to move back.