How can I make a character tilt when walking up a curve?

I am looking for a way to make your character tilt while going up a curve, but I cannot find any tutorials that work anywhere, Any help?

5 Likes

You could probably make a raycast that goes under the player to detect a part, and then manipulate the Character’s RootJoint.Transform to be aligned with the part that was found.

1 Like

I had too much trouble the first time I used raycasts, anyways, Raycasts would detect a wall or something like that and tilt like crazy

well, you can use RaycastResult.Normal to get the angle of the ray. Raycasting is probably the fastest way to do it.

1 Like

But the raycast goes in one direction, and the orientation is always the root part orientation…

1 Like

Could you elaborate on always RootPart Orientation?

If you want the ray to be facing down relative to the HumanoidRootPart, it should be like this:

local Root = Character.HumanoidRootPart
Result = workspace:RayCast(Root.Posiion, Root.CFrame:VectorToWorldSpace(Vector3.new(0,-10,0)) -- ray pointing down relative to root part

Hey. What you want to do is regularly update the C1 value of your Character.HumanoidRootPart.RootJoint, based off the pitch of the surface that the character is standing on.

You can use whatever step to update it regularly but here is the expression I would use for transforming the normal into a nice usable radian.

s = normal X rightVector
pitch = asin(-sâ‚‚)

in code:

pitch = math.asin(-RaycastResult.Normal:Cross(HumanoidRootPart.CFrame.rightVector).Y);

This takes the normal (a vector which is perpendicular to the surface), crosses it with the rightVector of the HumanoidRootParts’ CFrame in order to get a slope vector up the surface in the direction you are facing, then extracts the pitch value which is what you want to tilt with.

Then, applying this is as simple as transforming the C1 value with CFrame.Angles (where C1 is the stored default value for C1).

Root.C1 = C1 * CFrame.Angles(pitch , 0, 0)

I would recommend tagging walls with collection service and then inserting them into the RayParams.FilterDescendantsInstances table to prevent the issues you were having with crazy tilts.

Here is my implementation if you want to take a full look:

local RunService = game:GetService("RunService")

local Character = script.Parent
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local LowerTorso = Character:WaitForChild("LowerTorso")
local Root = LowerTorso:WaitForChild("Root")
local C1 = Root.C1
local RayParams = RaycastParams.new()
RayParams.FilterDescendantsInstances = {Character}
RunService.RenderStepped:Connect(function()
	local RaycastResult = workspace:Raycast(HumanoidRootPart.Position,Vector3.new(0,-10.5, 0), RayParams)
	if RaycastResult then
		local pitch = math.asin(-RaycastResult.Normal:Cross(HumanoidRootPart.CFrame.rightVector).Y);
		Root.C1 = C1 * CFrame.Angles(pitch , 0, 0)
	else
		Root.C1 = C1
	end
end)
6 Likes

I think that the ray will be aiming a specific direction relative to a part, but never change orientation

For some reason, I placed it in a local script in StarterCharacter and it does nothing?

I want to achieve something almost like Mario 64 tilts the main character on slopes

Are you trying with your Character as R6? His code works only for R15 , I believe that you could make some changes and make it work for R6 too.

1 Like

R6 version please, I mainly use R6 because trillions of bones get me under pressure

(DON’T DISAPPEAR ON ME AGAIN!)

The character clips trough the curves now

image

Any Idea how I can fix this?

ah, That’s not how Raycasting works. The ray is relative to the world unless if you do math to make it local to a part. @emperormicah’s code is exactly how I would go about doing this.

(Don’t dissappear on me!:cry:)

I just managed to get the code working how I want it to look but, The character is not moving properely on slopes and clipping on high angles (How can I make a character tilt when walking up a curve? - #13 by ProGaming7894) and I have no Idea how to fix this since I have no expirience scripting Motor6D things

What’s happening is that it’s rotating the character, however it also needs to offset the character in position relative to the angle. What I would do is for every stud above 0 in C1.LookVector.Y, add 1 stud (or more) to the C1.Position. So something like this:

Root.C1 = C1 * CFrame.Angles(pitch , 0, 0)
Root.C1 = Root.C1:ToWorldSpace(CFrame.New(0,Root.C1.LookVector.Y,0))

Also, sorry for being absent. I don’t check the forums ofren

R6 version

local RunService = game:GetService("RunService")

local Character = script.Parent
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local Torso = Character:WaitForChild("Torso")
local Root = HumanoidRootPart:WaitForChild("RootJoint")
local C1 = Root.C1
local RayParams = RaycastParams.new()
RayParams.FilterDescendantsInstances = {Character}
RunService.RenderStepped:Connect(function()
	local RaycastResult = workspace:Raycast(HumanoidRootPart.Position,Vector3.new(0,-10.5, 0), RayParams)
	if RaycastResult then
		local pitch = math.asin(RaycastResult.Normal:Cross(HumanoidRootPart.CFrame.rightVector).Y);
		Root.C1 = C1 * CFrame.Angles(pitch , 0, 0)
	else
		Root.C1 = C1
	end
end)
1 Like

Nothing seems to be going on, the camera acts werid tough.

1 Like

try multiplying the LookVector.Y and see if that does anything

Now the clipping is even worse when multiplying, and plus, the camera moves so strangely