Character keeps glitching when on ramp

It would be 165 degrees at the bottom of the hill, and I believe 195 degrees at the top(?) This is some weird mathin 3D space, but 2 vectors pointing towards each other is 180 degrees in 2D space.

I found math for the “angle between 2 vectors” on this forum somewhere. I was using it find whether 2 models could see each other, but I’m certain its the same formula here. Check this thread out that talks about it in detail. If this isn’t working for you, I can dig through my game tomorrow and see what worked for me.

Best way to get the angle between two vectors? - Help and Feedback / Scripting Support - DevForum | Roblox

idk what that would do to help?

The angle should tell you when the board is not flush with the ground, which is what I thought you were trying to fix in the second video. It’s looking a lot better!

yeah but tilts the wrong way X_X

You might get a CFrame expert stop by who can do this in an instant, but I need practice so I’ll take a crack at it.

This is probably the solution you seek. I put the code into a heartbeat function and set “bp” and “rcf” to the skateboard outside the function.

Make Part Match Part Below - Help and Feedback / Scripting Support - DevForum | Roblox

I just cant wrap my head around this… so how can i put this cframe stuff into the balancing

Lol, your force equation is above my head, but the solution I linked would potentially replace your ray (since that’s what this one does as well), and fix the tilt.

I would scrap using the humanoids orientation alltogether, because no matter how much you doctor it up its still the wrong angle at the end of the day
Ill be going with an angle approach like @GolgiToad described

Instead of humanoid.Orientation.X, try:

local dotX = skateboardlookvector:Dot(normalVector)
local orientX = (math.deg(math.acos(dotX))-90)*math.sign(dotX)

Instead of humanoid.Orientation.Z, try:

local dotZ = skateboardrightvector:Dot(normalVector)
local orientZ = (math.deg(math.acos(dotZ))-90)*math.sign(dotZ)

I highly doubt this will work first try but hopefully it will set you on the right track
Some basic troubleshooting would be making sure the look vector of the skateboard is actually forwards and that the right vector of the skateboard is actually facing right

Also you might want to mess with the first argument of your PID, I have no clue what it does but it might have undesired effects

1 Like

what would normalVector be defined as?

The normal of the raycast straight down at the center of the skateboard

Wait so is this still using a pid or the other thing you got me confused

Yes, simply take your original code and replace the humanoid angles with those calculated angles
You might have to mess with the first argument of the pid

what do you mean the first argument? like the kp and ki and stuff?

I mean you might have to mess with hnZ and hnX and make it what you originally had before ever messing with it to try to fix the angle issue

I dont know the orientZ and orientX thing is using the normal but that was the point of the hnX and hnZ

Does it work with a set value (like 7) like you originally had?

What do you mean 7? the pid needs kind of like a zero point that it aims to go to and im not sure how a vector would work with that

Is the first argument of your PID script not the proportion, kp?

kP = 0.9
kI = 0
kD = 0.2
min = -100
max = -min
local bpidZ =,kI,kD,min,max)
local bpidX =,kI,kD,min,max)

	local dotX = Board.CFrame.LookVector:Dot(normalVector)
	local hnX = (math.deg(math.acos(dotX))-90)*math.sign(dotX)
	local dotZ = Board.CFrame.rightVector:Dot(normalVector)
	local hnZ = (math.deg(math.acos(dotZ))-90)*math.sign(dotZ)
	local orientX = hrp.Orientation.X
	local orientZ = hrp.Orientation.Z
	--if kl == true then
	--	hnX = hnX + 0.22
	--elseif kr == true then
	--	hnX = hnX + 0.22
	--elseif manual == true then
	--	hnX = hnX + 0.22
	local balanceForceZ = bpidZ:Calculate(hnZ*100,orientZ,dt)
	local balanceForceX = bpidX:Calculate(hnX*100,orientX,dt)
	vf.Force =,0,balanceForceX)*75