Skip to content
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

Occasional jitter when KinematicBody2D moved in _physics_process() #41380

Closed
2nafish117 opened this issue Aug 19, 2020 · 6 comments
Closed

Occasional jitter when KinematicBody2D moved in _physics_process() #41380

2nafish117 opened this issue Aug 19, 2020 · 6 comments

Comments

@2nafish117
Copy link
Contributor

Godot version:
3.2.1 and 3.2.2

OS/device including version:
Windows 10, 8Gb RAM, Nvdia Geforce 920M (Driver version 425.31), GLES3 (probably occurs in GLES2 as well)

Issue description:
The docs say to use move_and_* functions in _physics_process(), but there is an occasional jitter that happens around every 2-3 seconds. Using move_and_* in _process() however doesn't have jitter.

Steps to reproduce:
Any kind of KinematicBody2D node when moved with move_and_* in the _physics_process(), but i have included a project that shows a comparison between:

  1. move_and_slide() used only in _physics_process()
  2. move_and_slide() used only in _process()
  3. and ive also tried using Engine.get_physics_interpolation_fraction() to interpolate a KinematicBody2D that moves in _physics_process() (my code for this is based on https://www.kinematicsoup.com/news/2016/8/9/rrypp5tkubynjwxhxjzd42s3o034o8)

On my laptop what i see is that 1. jitters occasionally, 2. doesnt jitter at all, 3. jitters really rarely, much less noticeable than 1.

Minimal reproduction project:
Interpolation.zip

I also have Interpolation.tscn as an Autoload, which was my implementation for the interpolation fractions, I then found Engine.get_physics_interpolation_fraction() is already provided in godot for this very reason. My InterpolatedTransform2D.tscn node has a boolean that lets you switch between my implementation and the Engine's version of interpolation fraction (both of them are identical afaik).

@Calinou
Copy link
Member

Calinou commented Aug 19, 2020

Try installing, enabling and configuring lawnjelly's smoothing-addon and see if the issue persists. It works well for many other people, so relying on a tried-and-true implementation might be better.

@lawnjelly
Copy link
Member

See also godotengine/godot-proposals#671.

Yes currently out of the box, with current Godot and physics, you will always get jitter from aliasing unless e.g. by chance your refresh rate matches your physics tick rate. This is well established and here are some possible solutions, all of which have pros and cons:

You can also get jitter from other sources, such as frame delta input / output delay variations, and physics behaviour.

@2nafish117
Copy link
Contributor Author

2nafish117 commented Aug 20, 2020

@Calinou the plugin works really nice, but i have concerns about how to structure my scenes with that method.
Lets say i want to make a 2d platformer player scene. I may have either a KinematicBody2D or a RigidBody2D (or as you call them physics representation) as the root node of the player scene, with sprites (visual representation) as its children, this is the usual way i may structure it.
With the plugin i have to separate them as a *Body2D node and a Smoothing2D with the sprites as its children. This makes it confusing and cumbersome to move the player around in the editor view (needing to move both of them together). If i make a Node2D as a common parent to both the physics rep and visual rep then from an external script it becomes harder to add forces or add velocities to the *Body2Ds.
Do you have a suggested way of structuring nodes to solve this?

In my implementation, the node structures for the player would remain the same, but to add interpolation to it i just add the InterpolatedTransform2D node as a child to the player, and have two additional function calls in the players _physics_process().
Also another idea that preserves the old way of structuring would be to have:

Player
    |---Smoothing2D
            |---Sprite

where Smoothing2D has set_as_top_level(true), which makes it independent of the parents transforms.

@lawnjelly one of my monitors has one of those weird refresh rates of 59.97 something, and jitters on it. I cant set the physics rate to floating values in the editor, only integers.
I hope godot 4.0 will have interpolation added within engine itself.

@lawnjelly
Copy link
Member

lawnjelly commented Aug 20, 2020

@lawnjelly one of my monitors has one of those weird refresh rates of 59.97 something, and jitters on it. I cant set the physics rate to floating values in the editor, only integers.

Although I mentioned it, I'm not personally a fan of fixing physics ticks rate to the frame rate these days. It used to be used when e.g. consoles were using either NTSC or PAL, but with modern devices you can get all kinds of frame rates including variable. So you end up needing to test the game in multiple versions.

If this was done properly in core, it would estimate in whole frame segments how physics ticks had passed on an update. So I don't think 59.97 would matter (there have always been those quirks).

Lets say i want to make a 2d platformer player scene. I may have either a KinematicBody2D or a RigidBody2D (or as you call them physics representation) as the root node of the player scene, with sprites (visual representation) as its children, this is the usual way i may structure it.
With the plugin i have to separate them as a *Body2D node and a Smoothing2D with the sprites as its children. This makes it confusing and cumbersome to move the player around in the editor view (needing to move both of them together). If i make a Node2D as a common parent to both the physics rep and visual rep then from an external script it becomes harder to add forces or add velocities to the *Body2Ds.
Do you have a suggested way of structuring nodes to solve this?

In my implementation, the node structures for the player would remain the same, but to add interpolation to it i just add the InterpolatedTransform2D node as a child to the player, and have two additional function calls in the players _physics_process().
Also another idea that preserves the old way of structuring would be to have:

Player
    |---Smoothing2D
            |---Sprite

where Smoothing2D has set_as_top_level(true), which makes it independent of the parents transforms.

I only recently changed the addon to artificially prevent this scene structure. Several people were using that scene structure already, and it can kinda work but can give nasty problems in some situations:

lawnjelly/smoothing-addon#7

Perhaps I was overzealous on this, especially in 2D. But with 3D the maths rapidly becomes 'explosive' (numerically unstable would be better wording lol).

If you find a better way of doing it for your purposes, go for it, and give us feedback so we can improve it. You are absolutely right it is useful to be able to move things and see feedback in the editor. Perhaps that is possible to do with the current system with an editor notification, maybe we can get this working. 👍

@2nafish117
Copy link
Contributor Author

2nafish117 commented Aug 20, 2020

If you find a better way of doing it for your purposes, go for it, and give us feedback so we can improve it. You are absolutely right it is useful to be able to move things and see feedback in the editor. Perhaps that is possible to do with the current system with an editor notification, maybe we can get this working. 👍

@lawnjelly Have you tried my sample project? Its not as polished as yours but gives a cleaner node structure.
Interpolation.zip
Basically it acts as a component on any *Body2D but requires 2 additional function calls in the _physics_process().
It is based on www.kinematicsoup.com/news/2016/8/9/rrypp5tkubynjwxhxjzd42s3o034o8 almost entirely.

Also for some reason im not entirely sure its working as expected (it is actually an extrapolation, but the links author named all of his classes interpolation). But hopefully you can be inspired from it.
The author moves the *Body each frame based on the interpolation factor, but resets the position to the original state, before the next _physics_process() is called.

@lawnjelly
Copy link
Member

lawnjelly commented Aug 20, 2020

@lawnjelly Have you tried my sample project? Its not as polished as yours but gives a cleaner node structure.

Yup. The problem with that approach I think is that by setting the rigidbody / kinematic body in the interpolator you are also setting up a feedback loop with the physics. Drop your physics tick rate to 5 ticks per second and you'll see what I mean.

In godot there's no way to set the render transform without also setting the physics afaik, hence the approach of decoupling the physics from the render object.

If instead you interpolate the icon directly, you might have more luck, but you will be dealing with a local transform relative to the parent, which is where the math can get kinda hairy in some situations.

You can on the face of it get a local transform from the previous transform to the current (of the physics rep in global space), and then interpolate this as the local transform of the icon, and I've used this kind of approach before. However there are some situations, especially in 3d where I had problems with it in terms of numerical stability, as far as I remember. This was what made integrating it into spatial such a pain.

In fact, just having another look, the smoothing addon can already do this in 2d. See the global in / global out flags (it is over a year since I wrote it so I forget some details). I made a commit a couple hours ago that undid the protection that I had added a few days ago to prevent using parents / grandparents as a target, at least for 2d, so you can try this out.

As I say I had a few people using the addon in this way already but I try to discourage it, as most of the bug reports were coming from people using it in this way and not understanding transforms. It is probably more important to get this separation in 3d though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants