godot
godot copied to clipboard
Collision Detection between CharacterBody2D and RigidBody2D not working(properly)
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
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.
}
Thanks for sharing the workaround. Do you know when this bug will be fixed?
Please create a minimal reproduction project in GDScript instead of C# for two reasons:
- Non-Mono builds of Godot are easier to set up and have less moving parts.
- This rules out C# being the cause of the bug.
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.
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
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.
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)
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
A current workaround is to disable the collision mask on the CharacterBody2D
that matches the layer that the RigidBody2D
is on.
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.
A current workaround is to disable the collision mask on the
CharacterBody2D
that matches the layer that theRigidBody2D
is on.
This fixed my issue, thanks!
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
A current workaround is to disable the collision mask on the
CharacterBody2D
that matches the layer that theRigidBody2D
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.
Exactly, the proposed workaround makes it likely that your CharacterBody2D will push any RigidBody2Ds into/through walls, floors, etc.
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
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.
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.
Just a heads-up, this also happens with StaticBody2D
A current workaround is to disable the collision mask on the
CharacterBody2D
that matches the layer that theRigidBody2D
is on.
A better workaround is to set recovery_as_collision to true.