Rotate Character To Terrain Plane

  1. What do you want to achieve? Keep it simple and clear!
    I want to orient the character so it’s 90 degrees to the terrain plane.
  2. What is the issue? Include screenshots / videos if possible!
    I’ve already made the script for the orientation, but I need a way to orient the character now.
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I’ve tried changing the Root Parts Orientation and the character freaked out.
3 Likes

change the orientation on the rootjoint motor6d

1 Like

Is it LowerTorso.Root motor6d? Because the HumanoidRootPart doesn’t have one.

2 Likes

idk i havent developed with r15 before

Yes. Root is the motor that should be changed.

This is my code so far, my character just freaks out whenever it runs

repeat wait() until game:IsLoaded()
local RunService = game:GetService("RunService")
local Player = game:GetService("Players").LocalPlayer
local TweenService = game:GetService("TweenService")
local Character = Player.Character or Player.CharacterAdded:Wait()

local part = Instance.new("Part")
part.Parent = workspace
part.Anchored = true
part.CanCollide = false

RunService.Heartbeat:Connect(function(deltaTime)
	local PrimaryPart = Character.PrimaryPart
	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {Character, part}
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	raycastParams.IgnoreWater = true
	local normalRay = workspace:Raycast(PrimaryPart.Position, Vector3.new(0,-5,0), raycastParams)

	if normalRay then
		Character.LowerTorso.Root.C1 = CFrame.new(PrimaryPart.Position, PrimaryPart.Position - normalRay.Normal)
		part.CFrame = CFrame.new(PrimaryPart.Position, PrimaryPart.Position - normalRay.Normal)
	end
end)

1 Like

While that may work for a part, updating Motor6Ds is a little more challenging and you’re gonna wanna do the following. Firstly I would save the character root’s C0 whenever they’re loaded in.

local defaultC0 = Character.LowerTorso.Root.C0

This will be kept outside the loop and will be referenced later on. Inside the loop what you have going on right now is mostly correct except that we will be editing the Root’s C0 not it’s C1.
In addition to that we are also gonna convert the normal’s vector to object space relative to the PrimaryPart.

local vector = PrimaryPart.CFrame:VectorToObjectSpace(normalRay.Normal)
Character.LowerTorso.Root.C0 = defaultC0 * CFrame.Angles(vector.z, 0, -vector.x)

With these changes your code is gonna look something like this:

repeat wait() until game:IsLoaded()
local RunService = game:GetService("RunService")
local Player = game:GetService("Players").LocalPlayer
local TweenService = game:GetService("TweenService")
local Character = Player.Character or Player.CharacterAdded:Wait()

local part = Instance.new("Part")
part.Parent = workspace
part.Anchored = true
part.CanCollide = false

local defaultC0 = Character.LowerTorso.Root.C0

RunService.Heartbeat:Connect(function(deltaTime)
	local PrimaryPart = Character.PrimaryPart
	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {Character, part}
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	raycastParams.IgnoreWater = true
	local normalRay = workspace:Raycast(PrimaryPart.Position, Vector3.new(0,-5,0), raycastParams)

	if normalRay then
		local vector = PrimaryPart.CFrame:VectorToObjectSpace(normalRay.Normal)
		Character.LowerTorso.Root.C0 = defaultC0 * CFrame.Angles(vector.z, 0, -vector.x)
		part.CFrame = CFrame.new(PrimaryPart.Position, PrimaryPart.Position - normalRay.Normal)
	end
end)
4 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.