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#test_motion behaving weird #16414

Closed
Tracked by #45334
dploeger opened this issue Feb 5, 2018 · 14 comments · Fixed by #55762
Closed
Tracked by #45334

RigidBody2D#test_motion behaving weird #16414

dploeger opened this issue Feb 5, 2018 · 14 comments · Fixed by #55762

Comments

@dploeger
Copy link

dploeger commented Feb 5, 2018

Godot version:
3.0.stable.official

OS/device including version:
macOS 10.13.3

Issue description:
Please see the attached test project, open and start Tester.tscn. The code is using test_motion to check for collisions when moving the left sprite one point to the right.

Maybe I just don't "get" test_motion right, but shouldn't that detect a collision? I also tried the same code in _process_physics, because I thought, that collisions would only be checked there, but with the same result.

I originally wanted to recreate another weird issue of three sprites where one sprite would be moved and test_motion would detect a collision with a completely unrelated sprite, however, I stopped here.

Steps to reproduce:

  • Open Test project
  • Open scene Tester.tscn
  • Check attached script
  • Run game with open scene
    => the script should output a collision information, instead it produces "NOT COLLIDING" as the result of test_motion is false.

Minimal reproduction project:
Test.zip

@dploeger
Copy link
Author

I just noticed, that the same behavior exists in Godot 2.1.4...

I simply don't get it. I tried it another way by reacting to mouse events and using test_motion before moving the sprites to the clicked target point. That works, but not in _ready or _physics_process. It's really strange.

@eon-s
Copy link
Contributor

eon-s commented Feb 20, 2018

The problem here are the segment shapes, these seem to be bugged in polygons too and do not trigger collision tests (like ray/shape casting).

@dploeger
Copy link
Author

@eon-s I just replaced them with 1 and 2 wide rectangles, but with the same effect. 😦

@eon-s
Copy link
Contributor

eon-s commented Feb 20, 2018

I'm surprised that works on ready o_O

Check this:
TestWithRectangles.zip

@dploeger
Copy link
Author

Yes, that works. But what's different to my test with rectangles? Can you spot anything?

Test.zip

@eon-s
Copy link
Contributor

eon-s commented Feb 21, 2018

It seems that test move fails on these shapes because the sides never touch the top/bottom ones, if you increase it one pixel or test move just on top on a side one, hits.

Also like if test_move is doing some kind of tunneling and does not implement CCD of any kind.

You can try Physics2DDirectSpaceState shape casting and Shape2D shape collision to see if these fail too (if penetrates thin shapes),

@dploeger
Copy link
Author

Yes. That works better:

	var parameter = Physics2DShapeQueryParameters.new()
	parameter.set_shape($FirstSprite/CollisionShape2D.shape)
	parameter.transform = $SecondSprite.transform
	var space = get_world_2d().get_space()
	var space_state = Physics2DServer.space_get_direct_state(space)

	var results = space_state.intersect_shape(parameter)

The results array then contains the shape of the second sprite.

However, test_motion seems to be seriously broken then. Should we let this ticket open?

@eon-s
Copy link
Contributor

eon-s commented Feb 25, 2018

Yes, 2D physics may get some improvements and need the reports, if we are lucky all these things will be revised at least for 3.1

@akien-mga
Copy link
Member

Can anyone still reproduce this bug in Godot 3.2.3 rc5 or any later release?

If yes, please ensure that an up-to-date Minimal Reproduction Project (MRP) is included in this report (a MRP is a zipped Godot project with the minimal elements necessary to reliably trigger the bug). You can upload ZIP files in an issue comment with a drag and drop.

@eon-s
Copy link
Contributor

eon-s commented Sep 4, 2020

This still happens on 3.2.3rc5 and the previous projects can reproduce the effect, here is an updated version of the last example provided.

The problem can be seen on the result of test_move on _ready and later on _input when clicking to trigger it again, using call_deferred does not make any difference on _ready.

Test_move_updated_323rc5.zip

@dploeger
Copy link
Author

dploeger commented Sep 4, 2020

@eon-s Thanks for updating! I was about to do this today, but you were quicker. ❤️

@akien-mga
Copy link
Member

CC @madmiraal

@madmiraal
Copy link
Contributor

This is the result of setting the margin to 0.0 (or anything less than or equal to 0.005; the test_motion_min_contact_depth). Therefore, it's related to #37798 i.e. the collision is detected, but it's not reported and so ignored. This issue is avoided by leaving the collision margin at the default 0.08, when calling test_motion() i.e.:
first_sprite.test_motion(motion, 0.08, collider)

However, there is still a bug here, and this issue is more generic than #37798. It's not resolved by #38529, because the unsafe distance is being correctly calculated. Rather, when the unsafe distance is calculated onto the pixel boundary, a collision is detected, but the overlap is zero. When using a margin, the overlap is increased by the size of the margin. However, when the sum of the margin and the overlap is zero (or more specifically, less than the CMP_EPSILON = 0.00001), no collision information can be extracted. Note, if the sum of the margin and the overlap is not zero, but less than the test_motion_min_contact_depth (0.005), the collision information can be extracted, but it's ignored. The key bug is that it's being ignored when using the unsafe distance i.e. the actual collision penetration is far greater. However, to resolve this issue completely would also require being able to extract information when the overlap is zero. Or, better yet, not detect a collision when the pixel overlap is zero i.e. zero pixel overlaps are considered safe, which would also resolve #23140.

Finally, it's worth pointing out that there is a script error in the latest minimal reproduction project: Test_move_updated_323rc5.zip, which makes the problem look worse than it actually is (i.e. it still fails even with the margin set to 0.08): the line first_sprite.translate(movement) is outside the if is_colliding: test; so the "Sprite" is moved regardless of whether or not there is a collision.

@dploeger
Copy link
Author

This, together with making the collision shapes of the movable tiles smaller than the actual sprite (because they really sit directly next to each other) works. It's not very intuitive, but thanks so far. Should we keep this issue open though?

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