+1 vote

I have a small Rigidbody2D icon that shoots Rigidbody2D bullets at a large Rigidbody2D icon. All rigidbodies have scale (1,1). Upon collision, the bullet spawns two sprites: a red burst to show the position of RigidBody2D.body_enter signal, and a green burst to show the position of state.get_contact_local_pos() method of the _integrate_forces function. So far no problem:

gif of explanation

The large icon is initially situated at origin (0,0), and the bullets slowly push it across the screen as intended. However, as the large icon moves, the collision bursts unexpectedly move in the same direction away from the collision point:

gif of linear movement

And things get strange when the large icon is rotated:

gif of rotational movement

The bullets are fired with the apply_impulse method as follows:

func _fire_bullet():
    var bullet = bullet_res.instance()
    bullet.set_pos(self.get_global_pos())
    bullet.set_z(1)
    self.get_parent().add_child(bullet)
    bullet.apply_impulse(Vector2(),Vector2(-1,0) * 500)

The red burst is created in the body_enter signal as follows:

func _body_enter(body):
    var red_burst = red_burst_res.instance()
    red_burst.set_pos(body.get_global_pos())
    self.add_child(red_burst)
    body._remove_bullet()

The green burst is created in the _integrate_forces function as follows:

func _integrate_forces(state):
    if (state.get_contact_count() > 0):
        var green_burst = green_burst_res.instance()
        green_burst.set_pos(state.get_contact_local_pos(0))
        self.add_child(green_burst)

Why are the collision positions moving away from the collision point?

Download link to example project: https://drive.google.com/file/d/0BwnfZQAEnciAek1oNW5NbG5rcEE/view?usp=sharing

in Engine by (1,302 points)

2 Answers

+1 vote
Best answer

You are actually hitting two problems here...

The first problem is that physics run behind logic (_fixed_process) for performance issues, as explained here: https://github.com/godotengine/godot/issues/4959

The second problem is that you are giving local coordinates (relative to their parent) to the bursts, while the engine gives you global coordinates -- that's why the appear to move.

by (1,566 points)
selected by

Thank you for the link and for the tip regarding local & global coordinates. I am posting the solution as an answer for better visibility.

As for the issue of physics running one frame behind logic, it is totally understandable and is actually welcomed if it improves performance.

+1 vote

This was solved based on Bojidar Marinov's tip regarding local vs. global coordinates. Actually it feels like more of a workaround, but the solution was to simply parent the bursts to the base node of the scene instead of the large icon. So instead of instancing a burst with self.add_child(green_burst), it should be self.get_parent().add_child(green_burst) as long as get_parent() points to the base node of the scene. And it works as expected:

gif solved

I suspect there may be a way of instancing a burst without parenting it to the scene root, by using transform/xform math... But that is beyond my skillset at this time.

by (1,302 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.