Questions about custom model slope alignment

hi all!! im not really great at coding so im already using this code How to get angle of platform player standing on - #12 by MrNicNac however the movement is very janky/snappy and it seems to lock forward to where the slope is going upwards, not being able to face downwards without turning, id like to fix the turning issue as well as make the transition from the group to the slope smoother ( / look more natural)

ive tried looking + implementing other code in the forum but as linked, its the only one thats been able to work with my custom model since :sweat_smile:

again i know like little to nothing about coding but am hoping to learn :] any help / explanation would be greatly appreciated

local char = script.Parent
local rootPart = char:WaitForChild("HumanoidRootPart")
local xzGyro = Instance.new("BodyGyro")
local yGyro = Instance.new("BodyGyro")
yGyro.MaxTorque = Vector3.new(0,3e5,0)
yGyro.P = 5e5
xzGyro.MaxTorque = Vector3.new(3e5,0,3e5)
xzGyro.P = 5e5
xzGyro.Parent = rootPart

while wait(0.5) do
	local params = RaycastParams.new()
	params.FilterDescendantsInstances = {char}
	params.FilterType = Enum.RaycastFilterType.Blacklist
	local result = workspace:Raycast(rootPart.Position, Vector3.new(0,-10,0), params)
	
	yGyro.CFrame = CFrame.new(rootPart.Position, rootPart.Position + char.Humanoid.MoveDirection*10)
	
	if (result) then
		print(result.Normal)
		local currentRightVector = rootPart.CFrame.RightVector
		local upVector = result.Normal
		local newFacialVector = currentRightVector:Cross(upVector)
		xzGyro.CFrame = CFrame.fromMatrix(rootPart.Position, currentRightVector, upVector, newFacialVector)
	end
	
end
1 Like

To align the cframe on the surface it should be just this: xzGyro.CFrame = CFrame.lookAt(result.Position, result.Position + result.Normal)

The code I originally wrote in that post was an example and the “janky” snappiness you’re referring to is because of this line

while (0.5) do

And should instead be converted to using the RunService to run every render frame.

2 Likes

The code attaches a part of custom type “BodyGyros” ( ? this must be using AngularVelocity type as well ) that rotate the Parent character. It uses a Raycast to check if there is a surface within 10 units below and if there is it assumes it must be walking on it. It does this every 0.5s, which is a very low rate if want a real time responsiveness, should be the reason for “jankiness”

yGyro applies angular force to the character to be parallel with the MoveDirection vector, which means when they’re on a slope they will be rotated forward or backward so character looks up or down

xzGyro does the same thing but uses a bit more math, for the X and Z axis alignments. They’re getting the up and right directions from the perspective of the object coordinate space only. For example, an object facing directly west, to their right is north, left is south. These are only relative to the object’s rotation. If the object was aligned with the world axis perfectly then these directions would match the global coordinate system.

They use the raycast result to determine the upVector, which is the normal of the surface it detected. A normal is a vector perpendicular to a surface, meaning it comes straight out of the wall, floor, or whatever surface.

They then do another math thing called a “cross product” of the right and up vectors. A cross product results in another vector perpendicular to the two vectors involved in the calculation. Because it used the X (right) and Y (up) components for calculation, the vector will be the Z (forward, backward) component. The object Z axis is the object’s forward and backward direction and it’s the last component needed, in the code it’s called newFacialVector. They then use all the components to construct the xzGyro CFrame which applies angular force to the attached character so that it aligns correctly.

1 Like

ou okay, how could i go about implementing the run service in the code (+ would that fix the issue of the character forcefully turning one direction?)

The character forcefully turning one direction is due to the way it’s using the xzGyro. It seems implemented that way on purpose because when you tap a key in Roblox you don’t instantly change direction to match your movement direction. Without it, a person could do a 180 degree turn with a key tap and only rotate halfway around. The character’s rotation could look quite strange in these cases.

Anyway remove the loop, make it a function and do

local RunService = game:GetService("RunService")
RunService.RenderStepped:Connect(thatfunction)