so I’m making a skating game and when you skate up a slope you stay upright but I want to detect if you’re going up a slope and rotate you on the Z axis to match the slope so it looks like you are going up it and not just sliding, how would i do this?
you’d use a raycast down from the player so you can get the normal of the surface and then some maths to determine the angle, or something with CFrames
Hey there! This is really general, but perhaps this tutorial on a sliding system may help with your skateboarding system.
ok, so I think I figured out how I might do this, at 9:12 on the video the guy talks about checking the previous Y value based on the new one to see where if the player is going up or down a slope, I think I might try this.
Ok, wait this video might be more helpful:
Slope
Character Orientation
A simple idea that comes to mind is casting two raycasts really close to eachother and then computing the derivative/rate of change.
I think computing the slope via the surface normal is far easier, more optimized, and will also allow for that correct rotation on the slope.
Alright @TheRealBoiAnimates. I found this snippet of code from the latest video I linked:
This essentially uses the cross product of the slope normal and the character right vector. This will not only find the slope, but it will return it relative to the character in the form of a Vector3. Here’s a diagram I made:
(ignore how its bugging out)
code i used
local slopePart = workspace:WaitForChild("SlopePart")
local block = workspace:WaitForChild("Block")
local plane = workspace:WaitForChild("Plane")
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = {plane, block}
local function visualizeVector(vector: Vector3)
local vectorPart = Instance.new("Part")
vectorPart.Size = Vector3.new(0.2, 0.2, vector.Magnitude)
vectorPart.CFrame = CFrame.lookAt(block.Position + vector/2, block.Position + vector * 1.5)
vectorPart.Anchored = true
vectorPart.CanCollide = false
vectorPart.BrickColor = BrickColor.new("Bright red")
vectorPart.Parent = workspace
return vectorPart
end
local normalVisual, rightVisual, slopeVisual, downVisual
while true do
local raycastResult = workspace:Raycast(block.Position, Vector3.yAxis * -100, raycastParams)
local rightVector = block.CFrame.RightVector
if raycastResult then
local normal = raycastResult.Normal
local slopeVector = normal:Cross(rightVector)
if slopeVector:Dot(block.CFrame.LookVector) < 0 then
slopeVector = -slopeVector
end
local _, _ = pcall(function()
normalVisual:Destroy()
rightVisual:Destroy()
slopeVisual:Destroy()
downVisual:Destroy()
end)
normalVisual = visualizeVector(normal * 5)
rightVisual = visualizeVector(rightVector * 5)
slopeVisual = visualizeVector(slopeVector * 5)
downVisual = visualizeVector(Vector3.yAxis * -5)
plane.CFrame = CFrame.lookAt(block.Position, block.Position + slopeVector)
end
task.wait()
end


