godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.63k stars 20.1k forks source link

Collision Detection between CharacterBody2D and RigidBody2D not working(properly) #70671

Open Vukbo opened 1 year ago

Vukbo commented 1 year ago

Godot version

v4.0.beta10.mono.official [d0398f62f]

System information

Windows 10 Home, Intel(R) Core(TM) i5-4210H CPU @ 2.90GHz 2.90 GHz,

Issue description

I want the Rigidbody2D to detect the Collision with the CharacterBody2D so I can program the behaviour of the RidiBody2D according to the Player.

The Issue:

https://user-images.githubusercontent.com/11051231/209828258-6e06fa64-1b3c-49a4-8c11-3fc1e777bda0.mp4

The RigidBody2D doesn't recognize the CharacterBody2D when he is on the ground and the CharacterBody2D is touching him from the side. (Example 01)

https://user-images.githubusercontent.com/11051231/209828325-540fd7a4-97f7-4bb8-a082-18ded349878c.mp4

The exception to this is when the RigidBody2D is falling on top of the CharacterBody2D, then he recognizes the collision. (Example 02)

Both bodies are on the same layer. RigidBody2D has max contacts > 0 and contact monitoring enabled. Still no collision between those. The collision between the StaticBody2D and the Rigidbody2D seems to work fine.

Steps to reproduce

Move the Player with Left and Right Arrow Keys and Space to Jump.

Expected Behaviour: When you move the Player into the standing RigidBody2D it should recognize its collision and print the name of the colliding node in the console.

Current Behaviour: Doesn't recognize the Player coming from the side, when standing. Seems to me that the RigidBody2D seems to be sleeping, yet can sleep is disabled.

Minimal reproduction project

CharacterBody2DCollisionIssueWithRigidBody2D.zip

heppocogne commented 1 year ago

I think this is a bug that should be fixed, but fortunately you can detect the collision in CharacterController.cs in this case.

CharacterController.cs: line37~

MoveAndSlide();
KinematicCollision2D kc = GetLastSlideCollision();  // or use GetSlideCollisionCount() and GetSlideCollision(intdex)
if (kc != null)
{
    Node colliderNode = (Node)kc.GetCollider();
    GD.Print(colliderNode.Name);    // This will print "RigidBody" when the player collides with the RigidBody.
}
Vukbo commented 1 year ago

Thanks for sharing the workaround. Do you know when this bug will be fixed?

Calinou commented 1 year ago

Please create a minimal reproduction project in GDScript instead of C# for two reasons:

leon-fenzl commented 1 year ago

As a work around, I added a new kinematic/Char body within the player, and it has its own collision layer, then I marked that collision layer on the ribigbody, so only the rigid bodies can detect this extra collider. I know it is not fancy, but it does the trick.

AttackButton commented 1 year ago

The problem is with the CharacterBody2D (or CharacterBody3D).

The RigidBody2D vs RigidBody2D works perfectly in these situations. The problem is only with the CharacterBody2D vs RigidBody2D or CharacterBody2D vs CharacterBody2D. It gets worse if it involves a moving platform.

Blue boxes == RigidBody2D Red boxes == CharacterBody2D

https://user-images.githubusercontent.com/25422687/223070780-f283db82-c01b-4401-8e6d-7b65f55a7d1d.mp4

characterbody_physics_tests.zip

AttackButton commented 1 year ago

As a work around, I added a new kinematic/Char body within the player, and it has its own collision layer, then I marked that collision layer on the ribigbody, so only the rigid bodies can detect this extra collider. I know it is not fancy, but it does the trick.

I will try that. I think the bug could be caused by the removing of the sync_to_physics from KinematicBody2d/CharacterBody2D since version 3.x.

KJSavinelli commented 1 year ago

I'm having this exact issue in 4.0.2 using gdscript. This is the only place I've seen a clear presentation of the exact issue that I'm struggling with.

I tried the work around of adding another CharacterBody2D to my original CharacterBody2D, and putting it on it's own collision layer, but the RigidBody2D is still not registering collision with it when it's on the floor (or close to the floor) and when hit from the side. (I edited the comment. Rebuilt my game in Godot 3.5.2. The bug is not present there and everything is working fine)

WiseNoodle commented 1 year ago

Figured I'd bring some other input from a slightly different use case: In Godot 4.0.3-stable I'm having the same issue where the CharacterBody2D does not move the RigidBody2D in a "Top-down" format.

For describing the video: I have a player that is a CharacterBody2D and the "shapes" are RigidBody2D's that have nothing changed in the inspector other than gravity set to 0.

Confirmed with another that it's not just my system. Same issue on Linux and Windows 10.

https://github.com/godotengine/godot/assets/95942443/b977ac0b-d29a-47c6-b857-60b898e611d5

WiseNoodle commented 1 year ago

A current workaround is to disable the collision mask on the CharacterBody2D that matches the layer that the RigidBody2D is on.

yurixander commented 11 months ago

I'm experiencing this very issue on my project. It seems the bug has yet to be fixed? I'm using Godot v4.1.1.stable.official [bd6af8e0e]. In my case, the collision does trigger if the RigidBody2D falls on top of the CharacterBody2D, as previously mentioned.

JuDelCo commented 11 months ago

A current workaround is to disable the collision mask on the CharacterBody2D that matches the layer that the RigidBody2D is on.

This fixed my issue, thanks!

Zoidster commented 10 months ago

I'll preface my comment by saying I am very new to Godot and Python (GDscript) but this seems to be the same issue I'm having and WiseNoodle seems to be correct. My player is a CharacterBody2D and the "Asteroids" are RigidBody2Ds

https://github.com/godotengine/godot/assets/148629354/6b205739-fd06-4ed3-8e47-4944dba8226d

Lazy-Rabbit-2001 commented 7 months ago

A current workaround is to disable the collision mask on the CharacterBody2D that matches the layer that the RigidBody2D is on.

This does fix the problem, but leads to another one: Imagine if a CharacterBody2D pushes a RigidBody2D and pushes it to a place where the rigid is against a wall, the rigid will behave weirdly. I have tested this and it proved to be true.

hunterloftis commented 3 months ago

Exactly, the proposed workaround makes it likely that your CharacterBody2D will push any RigidBody2Ds into/through walls, floors, etc.

codemeow commented 2 months ago

I have the same issue, but my RigidBody2D falls from above on the CharacterBody2D. Sometimes it triggers the collision and sometimes it's not. The big box is colliding, but a small debrees is not, it pushes my player into the ground and I cannot apply force to the RigidBody because I have no collision despite having it pushing me into the ground

image

        int count = GetSlideCollisionCount();
        for (int i = 0; i < count; i++) {
            KinematicCollision2D c = GetSlideCollision(i);
            if (c.GetCollider() is RigidBody2D) {
                RigidBody2D body = c.GetCollider() as RigidBody2D;
                GD.Print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>COLLIDED! " + body.Name);
                body.ApplyCentralImpulse(-c.GetNormal() * push_force);
            }
        }

I never detect the collision here.

andrew-suh commented 1 month ago

I'm also not seeing collisions between a stationary staticbody2D and a characterbody2D. My workaround is setting up the collision check within the characterbody2D script.

vvvvvvitor commented 1 month ago

Just a heads-up, this also happens with StaticBody2D

vvvvvvitor commented 1 month ago

A current workaround is to disable the collision mask on the CharacterBody2D that matches the layer that the RigidBody2D is on.

A better workaround is to set recovery_as_collision to true.