Hi everyone. Honestly, i resisted asking for help about this. But i have long time finding a solution, and how i don’t know Math beyond some stuffs, i’m stuck on this.
local function Aligned_MoveDir(moveDirection : Vector3, surfaceNormal : Vector3) : Vector3
surfaceNormal = surfaceNormal.Unit
if surfaceNormal.Magnitude == 0 then
return moveDirection
end
local upVector = Vector3.yAxis
local Axis = upVector:Cross(surfaceNormal)
if Axis.Magnitude < 1e-5 then
Axis = upVector:Cross(Vector3.zAxis)
end
Axis = Axis.Unit
local dotProduct = upVector:Dot(surfaceNormal)
dotProduct = math.clamp(dotProduct, -1, 1)
local angle = math.acos(dotProduct)
local rotation = CFrame.fromAxisAngle(Axis, angle)
local alignedMoveDirection = rotation:VectorToWorldSpace(moveDirection)
return alignedMoveDirection
end
Works perfectly on plane surfaces, ramps, and plane ceilings… but not in sphere, especially when are Upside Down.
this is beacause Axis is product of UpVector and Normal, UpVector is yAxis (a global axis), when the normal is opposite to UpVector (upside down), the direction can be anything (or so i understand).
I tried to detect when Normal is upper than 90°, and flip upVector to -UpVector, and works when are upside down… but when you want to walk around the sphere, you cannot pass the “equator”, because the input be inverted in some decimal upper 90°. Example: W becomes S… but in one decimal lower than 90° the input be W again… and that be a loop.
Sorry if i write this like someone what doens’t know the english gramatic, i dont know fully english. And i dont have anyone what have knowledge about scripting or math to talk about.