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

Collision Normals are not being accurately reported from move_and_collide() on non CSG meshes #67550

Open
Gamepro5 opened this issue Oct 17, 2022 · 5 comments

Comments

@Gamepro5
Copy link
Contributor

Godot version

4.0 Beta 3

System information

Windows 10; AMD Ryzen 7 3700X 8-Core Processor

Issue description

This issue is a bit hard to describe. Essentially, When colliding on corners or shapes, the surface normal does not get reported by move_and_collide() accurately. Let me give some examples.

Chapter One:

If the player's collision hull is a rectangle (stretched square), the following normals are reported:

Cube collision hull on StaticBody3D Corner

image
Notice how, despite colliding at a corner, only one of the two normals is reported. (two collisions are detected but only one normal is logged) This behavior is inconsistent with the same shape but as a csg. (It works correctly on CSGs)

Cube collision hull on CSGBox3D Corner:

image

If the player's collision hull is a cylinder, the following normals are reported:

Normals are correctly reported on cylinder shapes, but not from the side (I will get to that in chapter 2).

Cylinder shape on a StaticBody3D Corner:

image
Correctly detects it here for some reason. It correctly detects them on both the Static body and the CSG.

Cylinder shape on a CSGBox3D Corner:

image

If the player's collision hull is a capsule, the following normals are reported:

Capsules have the same issues as the square, but the round shape of the capsule prevents the player from actually moving because the wrong collision normal causes the next move_and_collide() to return a collision and therefore stop.

Capsule shape on StaticBody3D Corner:

image

Capsule shape on CSGBox3D Corner:

image

Chapter 2

Presumably for the same reason as the capsule collision on StaticBody3D corner from chapter 1, a similar issue can occur on walls. This only happens with cylinder shapes.
image
As you can see, we are on the corner of a wall. The collision normal reports suggest that we are not on a wall because they all report the floor. However, we cannot move. We can't move because move_and_collide() detected a collision for some reason. Move and collide often suffers from issues of detecting collisions and stopping even if the direction of motion would not cause a collision. In this example, the collision is presumably detected instantly because the player is intersecting the corner of this wall, so it stops motion. However, a wall collision normal isn't reported so there isn't much I can do about it.

I made this video that shows these issues in action

Steps to reproduce

  1. Download the project.
  2. Change the collision shape at will to test each condition.
  3. Click run and walk up slopes to test.

Minimal reproduction project

https://github.com/Gamepro5/Custom_CharacterBody3D_Movement_System/tree/1be17d8578a6975d9f35d317cdff8b30553d82df

@rburing
Copy link
Member

rburing commented Oct 18, 2022

The corner issues are probably due to incorrect use of non-uniform scaling in your project.

To reproduce what you are seeing more minimally (see the project attached below):

Start a new empty Godot project. Create a new 3D scene. To the 3D scene add a CharacterBody3D with a CollisionShape3D child with its shape set to a BoxShape3D. Add a script to the CharacterBody3D that moves downward using move_and_collide (setting max_collisions to at least 2) and prints all collisions. To the 3D scene add a StaticBody3D with a CollisionShape3D child with its shape set to a BoxShape3D. Rotate the StaticBody3D by 45 degrees on the z-axis and scale it by (5, 0.1, 5). Position the CharacterBody3D so that it lands on the top corner of the StaticBody3D. This results in two collisions being reported, both (0.707108, 0.707105, 0), similar to your report.

To fix this setup, remove the non-uniform scaling (5, 0.1, 5) from the StaticBody3D by resetting it to (1, 1, 1), and instead: in its CollisionShape3D, set the BoxShape3D resource's size property to (5, 0.1, 5). Visually it will look the same as before, but now the setup is such that the physics engine can work with it correctly. When running the scene with this setup, two collisions are reported, both (0, 1, 0), as desired.

Both scenes are included in the attached minimal project normals_on_corners.zip (enable Debug -> Visible Collision Shapes if you want to see something when running the scenes).

Basically, the rule is: don't scale CollisionShape3D nodes non-uniformly (and that includes scaling the parent body non-uniformly), set the size of the shape resource instead. (Note that the shape resource might be shared; in that case right click and press Make Unique if you don't want to change the size of the other collision shapes using the same resource.) Please let us know what issues remain after fixing your project to respect this rule.

Probably we should add more warnings in the documentation and in the editor, regarding non-uniform scaling of collision shapes.

(The CSG nodes' collision is a ConcavePolygonShape3D; those are probably more forgiving of transformations, since they are just a collection of faces.)

@Gamepro5
Copy link
Contributor Author

I think I understand. This would make creating maps a lot harder though: Not only do I have to change the size of box shape 3d, I also then have to change the mesh instance so it matches the shape. This means I can't drag to scale on the preview anymore, unless I'm missing something.

@Zireael07
Copy link
Contributor

Your meshes seem to be just boxes though? Or close enough? Just use their AABB as the size of the box shape 3d, or note down your current size*scale and hand enter the correct values.

Yes, we definitely need more warnings about scaling collision shapes, people keep running into these kind of problems.

@yosoyfreeman
Copy link
Contributor

yosoyfreeman commented Oct 21, 2022

If scaling collision shapes almost always lead to problems and have no benefits, why the engine allow it? There is some specific user case for it? It could not be fixed to 1?

In the other hand, drawing prefabs and scaling them is a common approach it most engines, so I'm quite curious about what is the Devs perspective about this.

Nice day!

@Gamepro5
Copy link
Contributor Author

@yosoyfreeman, @rburing told me that improving this is something they are working on because most people don't know that scaling is a bad idea. Until they do, however, a warning in the editor would be a good start.

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

4 participants