godotengine / godot

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

Inaccurate cast_motion in GodotPhysics #66072

Open narcissawright opened 1 year ago

narcissawright commented 1 year ago

Godot version

v4.0.beta1.official

System information

Windows 10, Vulkan

Issue description

Shapecast (cast_motion) in GodotPhysics returns noticeably inaccurate results - enough to cause visible jitter or choppiness. The same cast_motion in Bullet physics would produce smooth results, but Bullet is no longer available.

Here I'm using a sphere cast to help with Camera placement, so the Camera does not go through surfaces. But the result jitters, and even when moved across the flat floor surface, the height of the Camera keeps changing, because of the cast_motion result not being accurate.

How I expect cast_motion to work: The result of cast_motion multiplied by query.motion should give a 3D position that would make the query.shape tangent to the surface, instead of a rough approximation.

None of the settings in Project Settings -> 3D Physics -> Solver help. I cannot achieve the same accuracy as Bullet Physics.

https://user-images.githubusercontent.com/49114816/190928715-2ce7a1d3-fb1f-4164-8582-2f44940872c8.mp4

Steps to reproduce

Use PhysicsDirectSpaceState3D.cast_motion with a SphereShape3D, placing the camera using the result of the cast_motion call. Once the distance becomes smaller, the inaccuracy becomes very obvious. See minimal reproduction project.

Minimal reproduction project

InaccurateShapecast.zip

iamshadow2008 commented 1 year ago

I can confirm that subsequent results on the same flat surface return wildly different values, as you described. I'm also having issues where the shapecast penetrates objects to it's full target_position if the object it's attached to is moving at literally any velocity besides zero, then slowly "recovers" as in rises to meet the colliding object's boundary, and then goes completely haywire.

No physics settings made an impact.

Raycasts have exactly the same issues as shapecasts, and I know the code works because it's flawless on Godot 3.5 (using bullet physics, godotphysics there fails also).

narcissawright commented 1 year ago

I tried replacing cast_motion with a CharacterBody3D node using move_and_collide. It gave the same inaccurate behavior as cast_motion. I also tried SpringArm3D, same thing. I guess anything that causes a shapecast will have the same behavior.

Raycasts have exactly the same issues as shapecasts

I tried replacing cast_motion with intersect_ray but it actually gave accurate results for me.

rburing commented 1 year ago

If cast_motion in Godot Physics should do only kinematic solving (as it currently does), then

https://github.com/godotengine/godot/blob/63c0dc690e06731224e88911ed16d1b798b681b5/servers/physics_3d/godot_space_3d.cpp#L314

the number of steps should be customizable instead of fixed to 8.

narcissawright commented 1 year ago

I see, so it solves it for 8 steps and then stops.. I noticed using a longer shapecast motion would cause higher inaccuracy, while shorter ones are better about where the surface is.

Makes me wonder about a solver that keeps iterating until the position of the shape is against the surface within some specified margin, instead of running for a fixed number of iterations.

Also curious what Bullet was doing internally for it to work so well.

baznzab commented 1 year ago

I think I also faced the issue related to this one. Shape cast returns inconsistent results time after time. I prepared and published example how to reproduce it here What my example does is just moving static body around and casts its shape 1m down the floor. I log shape cast travel every frame. Most of the time result is okay but there are times when shape travels way too far. I commented it inside scripts/player.gd Also what I noticed is that when floor shape is smaller, result is more consistent. And when using WorldBoundaryShape3D result seems to be okay all the time.