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

RigidBody2D is rendered twice if using custom_integrator #56049

Closed
jpVm5jYYRE1VIKL opened this issue Dec 18, 2021 · 8 comments
Closed

RigidBody2D is rendered twice if using custom_integrator #56049

jpVm5jYYRE1VIKL opened this issue Dec 18, 2021 · 8 comments

Comments

@jpVm5jYYRE1VIKL
Copy link

jpVm5jYYRE1VIKL commented Dec 18, 2021

Godot version

3.4 stable

System information

Arch

Issue description

When used RigidBody2D with self.set_use_custom_integrator(false) . In accordance with documentation it means that used internal integrator and after it used additional integrator from _integrate_forces.

Problem that engine automatically render scene after internal integrator and one more time after _integrate_forces. Due it in some cases appears sprite flickering.

I created small project which illustrate problem.
To see issue need to start scene and press and hold button left icon will start to move and in one point . Sprite will reach point on screen where start flickering. It means that scene rendered once after exit from internal force integrator and one more time after exit _integrate_forces.
Expected that render of RigidBody2D will start only after finish _integrate_forces if it is overridden and not between internal and _integrate_forces

extends RigidBody2D


var viewport_rect : Rect2
var playfield_center : Vector2
var playfield_size : Vector2


# Called when the node enters the scene tree for the first time.
func _ready():
	self.viewport_rect = self.get_viewport_rect()
	self.playfield_size = self.viewport_rect.size
	self.playfield_center = self.viewport_rect.size / 2
	
	self.position = self.playfield_center
	self.visible = true
	
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
	self.set_gravity_scale(0.0)
	self.set_linear_damp(1.0)
	self.set_mass(1)
	self.set_use_custom_integrator(false)
	self.set_mode(RigidBody2D.MODE_CHARACTER)
	
	

func _input(event):
	if event is InputEventKey:
		if event.get_scancode() == KEY_ESCAPE:
			self.get_tree().quit()
		if event.get_scancode() == KEY_LEFT:
			self.apply_central_impulse(Vector2.LEFT * 300)


func _integrate_forces(state):
	var current_transform : Transform2D
	current_transform = state.get_transform()

	print(current_transform.origin.x)
	if current_transform.origin.x < 128:
		current_transform.origin.x = 128
		state.set_linear_velocity(Vector2.ZERO) 

	state.set_transform(current_transform)	


Steps to reproduce

  1. start scene
  2. press and hold left until sprite start flickering

Minimal reproduction project

tests.tar.gz

@Calinou Calinou changed the title Godot render RigidBody2d twice if used custom_integrator RigidBody2D is rendered twice if using custom_integrator Dec 18, 2021
@jpVm5jYYRE1VIKL
Copy link
Author

Bug demo

fff.mp4

@jpVm5jYYRE1VIKL
Copy link
Author

3.4.1 and 3.4.2 also affected

@jpVm5jYYRE1VIKL
Copy link
Author

3.4.4 problem still persist and not fixed

@Calinou
Copy link
Member

Calinou commented Jun 14, 2022

Minimal reproduction project: tests-project.zip
(tests.tar.gz linked in OP is not a complete project that runs as-is, since there is no project.godot file included.)

Video recording of the above MRP on 3.5.rc (40963cc):

simplescreenrecorder-2022-06-14_14.40.12.mp4

I'm pressing the left arrow key intermittently, which is where you can see the subpixel position change occurring. In any case, the sprite never appears twice, but it does flicker due to rapid position changes. (If it looks like the sprite appears twice, this is because monitors have some amount of ghosting, with some having significantly more ghosting than others.)

I'm not 100% convinced this is a bug. There are many potential issues I see here:

  • Impulse is added in _input(), which is called multiple times per physics frame if there's more than one input event occurring in a given physics frame.
  • Clamping coordinates should be done with colliders (or axis lock in 3D, if relevant).

@jpVm5jYYRE1VIKL
Copy link
Author

jpVm5jYYRE1VIKL commented Jun 14, 2022

if to set in example self.set_use_custom_integrator(true) than still issue persist but in accordance with code origin.x must be never be lower than 128 . Feels like that physics applied to object without respect to set_use_custom_integrator value. i tried to do different combinations without any success . Still think that this is bug.
Clamping coordinates should be done with colliders (or axis lock in 3D, if relevant)
In godot exist problem that colliders quite often does not catch quickly changing coordinates for example in cases if object moved using mouse with event.get_relative(). So using colliders is not an options . They work good only in case if object move slow.

if to speak about original example as i understand properly then in case if set_use_custom_integrator(false) than all have to be executed in following order :

  1. _integrate_forces
  2. process physics in accordance with values was set in _integrate_forces

But as i see executes following way :

  1. process physics
  2. _integrate_forces
  3. process physics in accordance with values was set in _integrate_forces

and this is why you see such jumps. I hope i not mistake anywhere.

@Calinou
Copy link
Member

Calinou commented Jun 15, 2022

In godot exist problem that colliders quite often does not catch quickly changing coordinates for example in cases if object moved using mouse with event.get_relative(). So using colliders is not an options . They work good only in case if object move slow.

Physics tunneling can be mitigated by increasing Physics FPS in the project settings, using larger collision shapes when possible, or using a raycast to check between the previous physics frame's position and the current physics frame. See #9071.

@jpVm5jYYRE1VIKL
Copy link
Author

Hi thanks . I understand that exist a lot of ways to masquerade problem. But in reality main issue that custom integrator executed after physical server modification and not before. Not exist sense to create custom integrator if it executed after physics already applied and frame already rendered.

This is really issue which i reporting. In current moment everything works following way .

event -> apply forces -> physical server calculate physics -> rendered -> execute custom integrator -> render again.

But in my opinion have to be following way :

event -> apply forces -> custom integrator -> physical server calculate physics -> render

@Calinou
Copy link
Member

Calinou commented Jun 15, 2022

I found out this is a duplicate of #11925.

@Calinou Calinou closed this as not planned Won't fix, can't repro, duplicate, stale Jun 15, 2022
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

2 participants