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

[2.1.4] Collision offset of Area2D when parent is in movement #11879

Open
ghost opened this issue Oct 6, 2017 · 12 comments
Open

[2.1.4] Collision offset of Area2D when parent is in movement #11879

ghost opened this issue Oct 6, 2017 · 12 comments

Comments

@ghost
Copy link

ghost commented Oct 6, 2017

Operating system or device, Godot version, GPU Model and driver (if graphics related):

  • OS: Ubuntu 17.04
  • Godot: 2.1.4
  • GPU: unrelated, but GTX 860m using the proprietary drivers

Issue description:

The scenario

  • I have a ship and a player (both KinematicBody2D)
  • The player can freely move on the ship (player is a child node of ship)
  • Ship has a cockpit, player should be able to enter the cockpit to fly the ship
  • The cockpit is a Area2D to detect a collision (i.e. if the player inside the cockpit, so the 'Action' key triggers the 'player-enters-cockpit' action)

The Problem:

  • In the beginning, ship and player are stationary. Player might move into the cockpit and enter it. Player may then accelerate the ship and jump out. Eventually, he might come back, but cannot enter the cockpit anymore because there is no collision detected by the Area2D
  • Depending on the velocity of the ship, the actual collision area of the Area2D will move ahead of the ship. I.e. there is an offset (see illustration below)
  • The higher the velocity, the higher the offset
  • If the velocity is constant, the offset is constant as well
  • The offset is always in the direction of flight. The rotation of the ship is irrelevant

Here's an illustration (desired/expected place of collision in a moving ship in red on the left, and the actual place of collision in red on the right):

dfss

Worth mentioning

  • If you enable Visible Collision Shapes in the debug tools, you won't see any offset at all. The shapes are obviously colliding
  • I made a test and manually calculated the collision detection, which produces correct results (i.e. the collisions are detected right, regardless of what the velocity is). A bit more specific: if I check for collision using collide() of RectangleShape2D for the player model and the Area2D inside _fixed_process(), I get correct results. However, this is not really practical, since I need to know all possible collision objects in advance... I would expect, that the body_enter and body_exit events honour the _fixed_process-ing (i.e. that the calculations which lead to these events are synchronous with _fixed_process)
func _fixed_process(delta):
    # ...

    # Workarround
    var player = get_node('../path/to/player')
    var bb_player = player.get_node('collision-model').shape
    var cockpit = get_node('../path/to/cockpit/location')
    var bb_cockpit = cockpit.get_node('collision-model').shape
	
    if bb_player.collide(player.get_transform(), bb_cockpit, cockpit.get_transform()):
        print('collision')
    else:
        print('no collision')

    # ...

Steps to reproduce:

  • I made a small demonstration project right here
  • You can only toggle between two velocities, but it shows the problem quite well I think
  • Use S to travel at a slow velocity (i.e. the hit detection works)
  • Use F to travel at a fast velocity (i.e. the hit detection wont work)
  • You can observe the body_enter and body_exit events in the print output
  • Traveling at slow speed should indicate "ENTERED" in the output. If you toggle to a fast speed, you should see, that the player left the cockpit according to the engine (indicated by "LEFT")
@ghost ghost added bug topic:core labels Oct 6, 2017
@ghost ghost added this to the 2.1 milestone Oct 6, 2017
@eon-s
Copy link
Contributor

eon-s commented Oct 14, 2017

Bodies and area are moving 100 units per fixed frame (6000 per second?), detection is going to fail that way for sure.

But fails anyway at around 1100 units with is a lot slower, not sure if the area or the kinematic child gets delayed for the Physics server (both area and body report position [0,0]).
Also happens using set_pos on the main body and with RigidBody2D in kinematic mode.

@ghost
Copy link
Author

ghost commented Oct 17, 2017

Bodies and area are moving 100 units per fixed frame (6000 per second?), [...]

Exactly

[...] detection is going to fail that way for sure.

Why so? Is there a maximum speed at which collision detection works properly?

@eon-s
Copy link
Contributor

eon-s commented Oct 17, 2017

Well, yes, if you move at high speed on a non CCD mode, you need to implement something for the case or the small hitboxes will be prone to fail on overlaps (a bit bigger shapes increase a lot the failure point value).

But the problem here is at slow speeds too and does not fail (so fast at least) with rigid bodies, so it should be something else.

@eon-s
Copy link
Contributor

eon-s commented Oct 21, 2017

Made a test with Area2D and it seems to work fine, the problem is only with KinematicBody2D like if the body position used by the server gets delayed a frame.

I'll try to test this on 3 too (so it gets more attention).

@ghost
Copy link
Author

ghost commented Oct 21, 2017

I wish I could help, but this was something I stumbled upon in my very first project. But I would be interested as well if it only affects 2.1.4 or also 3.0.

@eon-s
Copy link
Contributor

eon-s commented Oct 21, 2017

Yes, affects 3 too.
Sample project:
KinematicHighSpeedBug.zip

Ping to @RandomShaper who knows better this kind of things.

@RandomShaper
Copy link
Member

I'll have a look ASAP.

@RandomShaper
Copy link
Member

I'm researching... So far I haven't found a way to fix it.

@Calinou
Copy link
Member

Calinou commented May 7, 2020

Does this problem disappear if you enable Sync to Physics on the KinematicBodies? See #3092 (comment).

@eon-s
Copy link
Contributor

eon-s commented May 7, 2020

On 3.2.2 b1, sync_to_physics cannot be used with move_and_collide, but even by changing positions directly and sync to physics enabled it fails at around 1800 pixels/sec in the example project.

@maridany1999
Copy link

Godot 4.2, the same happened to me, I managed to fix this issue by writing the raycast collision detection through code (in the Physics Process) rather than using the RayCast3D node.

@mathieuguyot
Copy link

mathieuguyot commented Apr 1, 2024

Enregistrement.de.l.ecran.2024-04-01.a.18.19.48.mov

On Godot 4.2 I have encountered this issue also:
In the example video, the player (a CharacterBody2D) is entering a cockpit (an Area2D). Those two elements are inside a ship that is a rigidBody2D that is move by propulsers (others rigidbodies2D). When ships moves fast, the player leaves the cockpit as shown in the log but in the game is still inside as shown on the video.
Collision with ship walls (staticBodies2D) and the player are well handled even at high speed.

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

6 participants