local bodySom = Instance.new("BodyGyro", script.Parent)
bodySom.Name = "wheelie"
while true do wait()
local value = 45 * script.Parent.CFrame.LookVector.magnitude
bodySom.CFrame = CFrame.new(script.Parent.Position, script.Parent.Position + script.Parent.CFrame.LookVector) * CFrame.Angles(math.rad(math.clamp(value, -45, 45)), math.rad(0), math.rad(0))
end

The Value of the Orientation(x) doesnt get really clamp Correctly.

What I want to achieve is that, I want to keep the part from updating from where it is facing and then rotate at a 45Â° angle, I tried using loop thinking that it is the solution but it just created another problem:

Im trying to make a bike wheelie so the while loop is basically to update the BodyGyroâ€™s CFrame to where part/player is facing by using the lookVector.

This is basically what happens(because if you look at the Properties of the BodyGyro > Orientation the value of the x,y,z just keeps adding up, so I tried using â€śmath.clamp()â€ť but it didnt really work):

EDIT: This should theoretically work? Not too sure though.

local part = script.Parent
local bodyGyro = part.BodyGyro
while true do
local ray = workspace:Raycast(part.Position, part.CFrame.UpVector * -20)
if ray and ray.Instance then
bodyGyro.CFrame *= (CFrame.new(ray.Position).Rotation * CFrame.Angles(math.rad(45), 0, 0))
end
task.wait(.05)
end

Im using the loop so that it always update the CFrame. Im trying to make it work in all directions where the part is facing, without the loop it doesnt really update.

just cache the position so no funny business happens

local bodySom = Instance.new("BodyGyro", script.Parent)
bodySom.Name = "wheelie"
local Cframe = script.Parent.CFrame
while true do wait()
local value = 45 * Cframe.LookVector.Magnitude
bodySom.CFrame = CFrame.new(Cframe.Position, Cframe.Position + Cframe.LookVector) * CFrame.Angles(math.rad(math.clamp(value, -45, 45)), math.rad(0), math.rad(0))
end

local bodySom = Instance.new("BodyGyro", script.Parent)
bodySom.Name = "wheelie"
local UpDir = Vector3.new(0,1,0)
while true do wait()
local Cframe = script.Parent.CFrame
local LookVector = -Cframe.RightVector:Cross(UpDir)
local value = 45 * LookVector.Magnitude
bodySom.CFrame = CFrame.new(Cframe.Position, Cframe.Position + LookVector) * CFrame.Angles(math.rad(math.clamp(value, -45, 45)), math.rad(0), math.rad(0))
end

if you want to make it accurate on steep surfaces just change the UpDir with the ray.Normal of a ray with direction -Y (aka workspace:RayCast(script.Parent.Position, Vector3.new(0,-5,0))