Hi there, you are experiencing this behavior because you are telling the game to set the character’s position (Raycast.Position in your code) to where your raycast hits the floor, and set the character to be facing the position where your raycast hits the floor plus its normal vector.
For example, in world coordinates, if the player was located at (0, 5, 0) and the raycast hit the floor at (0, 0, 0), your code is telling the character to position itself at (0, 0, 0), facing toward (0, 0, 0) + (0, 1, 0) = (0, 1, 0).
Rather than using the lookAt constructor for this, try using Cframe.fromMatrix().
which lets you position/orient your player by passing in its position, right, up, and look vectors. The following code shoots a raycast downward to find the surface normal, repositions the player and treats the normal vector as the character’s UpVector.
-- Local script
-- Should probably run this via Runservice.PreSimulation so the player wont see themselves moving
-- Raycasting is cheap. You should be more than able to do this every frame.
local characterCFrame = playerCharacter.CFrame
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = {playerCharacter};
local raycastResult = workspace:Raycast(characterCFrame.Position, characterCFrame.UpVector * -100, --[[Any distance you want]] raycastParams)
if raycastResult then
local upVector = raycastResult.Normal;
local rightVector = characterCFrame.RightVector;
local lookVector = characterCFrame.LookVector;
-- Construct the player's new CFrame
local finalCFrame = CFrame.fromMatrix(characterCFrame.Position, rightVector, upVector, lookVector);
playerCharacter:PivotTo(finalCFrame);
end
This should work nicely for ramps and small gradients. Players tend to fall over at sharper angles, which you could try to fix by using Humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
but you may also have to do some trickery with the player’s gravity in order to have them walk up vertical walls.
If all else fails and you don’t want to do it yourself, definitely give EgoMoose’s wall stick implementation a try.