Godot Version
4.3
Hi all, first time posting here, not sure if to post this here in help/programming or physics. It’s more of a vector math problem than a collision body issue. Sorry if I’m in the wrong place.
Background
Short and to the point: I’m using the floating-collider-and-raycast method for my player character and moving it using camera relative direction(intended_direction
). The raycast checks ground below and takes the normal of the surface we’re moving on. The character movement uses the ground’s normal (ground_normal
) vector for smooth consistent movement on ramps and inclines though I do apply a correction to the character’s vertical position using the raycast after applying physical movement.
Problem
I noticed that when moving on certain inclines the movement of the player character becomes skewed: for instance you’d hold forward but the character would move in a somewhat diagonal direction rather than properly forward of the camera’s heading. I normally use vector3 final_calc = Plane(ground_normal).project(intended_direction)
to take the current incline into account and this seems to be what’s causing this distortion of direction. I created a dedicated scene that uses raycasts to visualize the vector calculations (red for simulated ground_normal
, blue for intended_direction
and yellow for the final_calc
calculation using stated method) and a plane mesh facing the ground normal for reference. And indeed, viewing it from the top, the Plane normal actually does rotate the final calculation vector away from the direction intended by the player by quite a bit!
For reference the simulated ground_normal
is x:0.47275, y: 0.534897, z:0.700281
Attempted Solutions:
I’ve figured all I really want from the ground_normal
an incline normal parallel with the intended_direction
so I made the purple raycast to represent an attempted fix: Vector3 plane_fix
.
-
I’ve tried making a temp vector3 that’s plane projected using the ground’s normal like usual. Then I take the vectors Y value and apply it to a vector that uses
intended_direction
’s X/Z values. This didn’t work out. While the yellowfinal_calc
cast sticks the surface of the reference plane perfectly the purpleplane_fix
will either rise from the surface of the plane or sink into in. -
Next thing I tried was making a stand-in ground normal by using Vector3.project:
stand_in = intended_direction.project(ground_normal).normalized()
thenplane_fix = Plane(stand_in).project(intended_direction)
. Ran that and still no joy, it produced similar results for the purple raycast as the method before. -
My more elaborate attempt for a solution: Taking the
intended_direction
and the world ‘up’Vector3.UP
and using those to create a cross product between the two, assigning the result to a vectorplane_norm
. I then used thisplane_norm
to Plane project theground_normal
(new_ground_norm = Plane(plane_norm).project(ground_normal)
in an attempt to isolate the vector ofground_normal
’s incline parallel tointended_direction
. Then appliedplane_fix = Plane(new_ground_norm).project(intended_direction)
but still, again, no success, I get similar behavior from the vector not sticking to the reference plane mesh while the raycast forfinal_calc
sticks smoothly to it.
Sorry if this post is a little wordy, it’s just I’ve hit a brick wall with this. I can’t seem to find a solution to this. Am I missing something here? Is there a function to Plane or Vector3 I’m not utilizing that could fix this? I was sure the last attempt would of worked out. Surely someone may have run into this too.
thanks.