How would I rotate a skinned mesh character based on a slope?

I am creating a game that uses skinned meshes. The starter character is small and light so I thought of adding “slope rotation” to him.

It is hard to find any posts that have a good solution to this.
I know this might be a crude drawing but it is a good enough example.

I’ve tried casting a ray down and using the normal to rotate the character. The character usually either vibrates(glitchy) or faces a completely different direction.

Another solution I found worked in a 2d game I’ve also created. But unsurprisingly it does not work in 3d.

I’ve also tried solutions other people have given, however, none of them work usually due to it being a skinned mesh and all.

local speedy = 0
local hrp = script.Parent.HumanoidRootPart
hrp.CFrame *= CFrame.new(0,50,0)
local uis = game:GetService("UserInputService")
local speedxz = 0
local onground = false
local dnray,dnray2
local dvector = hrp.CFrame.UpVector*-2.8
local movedir = Vector3.zAxis
local function ray(origin:Vector3,dir:Vector3,filtertype:Enum.RaycastFilterType,filter,ignorewater:boolean)
	local rcp = RaycastParams.new()
	rcp.FilterType = filtertype
	rcp.FilterDescendantsInstances = filter
	rcp.IgnoreWater = ignorewater
	return workspace:Raycast(origin,dir,rcp)
end
local function getRotationBetween(u, v, axis) --thanks, dthecoolest!
	local dot, uxv = u:Dot(v), u:Cross(v)
	if (dot < -0.99999) then return CFrame.fromAxisAngle(axis, math.pi) end
	return CFrame.new(0, 0, 0, uxv.x, uxv.y, uxv.z, 1 + dot)
end
game:GetService("RunService").RenderStepped:Connect(function()
	speedy -= .5
	hrp.CFrame *= CFrame.new(0,speedy/10,0)
	onground = false
	if ray(hrp.Position,dvector,Enum.RaycastFilterType.Blacklist,{script.Parent},true)then
		repeat
			hrp.CFrame *= CFrame.new(0,.05,0)
			dnray2 = ray(hrp.Position,dvector,Enum.RaycastFilterType.Blacklist,{script.Parent},true)
			dnray = dnray2 or dnray
		until not dnray2
		hrp.CFrame = hrp.CFrame:Lerp(hrp.CFrame*getRotationBetween(hrp.CFrame.UpVector,dnray.Normal,movedir),.1)
		onground = true
		speedy = 0
	end
	dvector = hrp.CFrame.UpVector*-2.8
	if not onground then
		hrp.CFrame = hrp.CFrame:Lerp(CFrame.lookAt(hrp.Position,hrp.Position+movedir),.4)
	end

	if uis:IsKeyDown(Enum.KeyCode.Space)and onground then
		speedy = 11
	end
	if uis:IsKeyDown(Enum.KeyCode.E)then
		speedy = 0
		speedxz = 0
		hrp.CFrame = workspace.SpawnLocation.CFrame * CFrame.new(0,10,0)
	end
	if script.Parent.Humanoid.MoveDirection ~= Vector3.zero then
		movedir = script.Parent.Humanoid.MoveDirection
		if onground then
			hrp.CFrame = hrp.CFrame:Lerp(CFrame.lookAt(hrp.Position,hrp.Position+script.Parent.Humanoid.MoveDirection)*getRotationBetween(hrp.CFrame.UpVector,dnray.Normal,hrp.CFrame.LookVector),.4)
		else
			hrp.CFrame = hrp.CFrame:Lerp(CFrame.lookAt(hrp.Position,hrp.Position+script.Parent.Humanoid.MoveDirection),.4)
		end
		speedxz += onground and .1 or .02
	end
	speedxz *= onground and .8 or .95
	hrp.CFrame *= CFrame.new(0,0,-speedxz)
end)

Here’s a video of what that looks like:


A good example of what a game with slope rotation looks like would be Sonic Speed Simulator.

3 Likes

@Prvqx it looks perfect to me mate it has no issues don’t worry about it

1 Like

It clearly looks broken, especially compared to another game with slope rotation. While moving, the character is only half-rotated, and on another slope, it’s rotated differently than it should. It’s very glitchy, and the player doesn’t even rotate when walking down the slope.

3 Likes

@Prvqx yea mate your right the code is differently broken but I think just redo it and see how it goes like change it a little bit add something else in

1 Like

The thing is that I don’t know what exactly to code since I don’t have any solutions.
henceforth, why I posted here.

1 Like

Look, I appreciate you trying to help me but I opened this thread for me to get help on this specific situation. If I found a solution from a tutorial or somewhere else I wouldn’t have posted.

2 Likes