I’ve been trying to make a hoverboard with bodyposition that is 4 studs off from the ground but anything I do it won’t go 4 studs off from the terrain/surface.
I also want it to match the angle the hoverboard is on or the surface it’s on, so the hoverboard will be the same orientation/angle as the terrain, or wedge for example. So basically I’m trying to have hoverboard physics, or a hoverboard suspension. I don’t know what I’m doing wrong
basically the problem is it’s too close to the ground, won’t match the same angle/orientation as the surface and won’t stay 4 studs off the ground.
here’s the script:
local model = script.Parent
local seat = model.VehicleSeat
local base = model.Base
local engine = base.Engine
local bg = base.BodyGyro
local bv = base.BodyVelocity
local velocityDecay = 0.8
local currentSpeed = 0
local maxSpeed = 50
local maxReverse = 12
local acceleration = 1.2
local steerRoll = 0.5
local steerAmount = 0.05
local yawVelocity = 0
local pitchTilt = 0
local targetPitch = 0
local pitchLerpSpeed = 0.05
local rollTilt = 0
local targetRoll = 0
local rollLerpSpeed = 0.05
local rot = {yaw = base.Orientation.Y, pitch = 0, roll = 0}
local playingSound = false
local enginePitch = 6
local forwardEnginePitch = 12
local backwardEnginePitch = 8
local anim = nil
local hoverHeight = 3
local suspensionStrength = 50
local suspensionDamping = 0.8
local function lerp(a, b, t)
return a + (b - a) * t
end
local function calcRot(yaw, pitch, roll)
return CFrame.Angles(pitch, 0, 0) * CFrame.Angles(0, yaw, 0) * CFrame.Angles(0, 0, roll)
end
local function added(child)
if child.ClassName == "Weld" then
local human = child.Part1 and child.Part1.Parent:FindFirstChild("Humanoid")
if human and seat:FindFirstChild("Animation") then
anim = human:LoadAnimation(seat.Animation)
anim:Play()
end
end
end
local function removed(child)
if anim then
anim:Stop()
anim:Destroy()
anim = nil
end
end
seat.ChildAdded:Connect(added)
seat.ChildRemoved:Connect(removed)
while true do
task.wait()
if seat.Occupant and not playingSound then
playingSound = true
engine:Play()
elseif not seat.Occupant and playingSound then
playingSound = false
engine:Stop()
end
if seat.Throttle == 1 then
engine.Pitch = math.clamp(engine.Pitch + 1, enginePitch, forwardEnginePitch)
currentSpeed = math.min(currentSpeed + acceleration, maxSpeed)
elseif seat.Throttle == -1 then
engine.Pitch = math.clamp(engine.Pitch + 1, enginePitch, backwardEnginePitch)
currentSpeed = math.min(currentSpeed + acceleration, maxSpeed)
else
currentSpeed = bv.Velocity.Magnitude
engine.Pitch = lerp(engine.Pitch, enginePitch, 0.1)
end
if seat.Steer == 1 then
yawVelocity = -seat.Steer * steerAmount
targetRoll = -steerRoll
elseif seat.Steer == -1 then
yawVelocity = -seat.Steer * steerAmount
targetRoll = steerRoll
else
yawVelocity = 0
targetRoll = 0
end
local origin = base.Position
local rayDir = Vector3.new(0, -hoverHeight-5, 0)
local ray = Ray.new(origin, rayDir)
local hit, hitPos, normal = workspace:FindPartOnRay(ray, model)
local desiredVel = Vector3.new()
if hit then
local distance = (origin - hitPos).Magnitude
local offset = hoverHeight - distance
desiredVel = Vector3.new(0, offset * suspensionStrength, 0)
end
if seat.Throttle ~= 0 then
local moveDir = base.CFrame.LookVector * (seat.Throttle == 1 and currentSpeed or -maxReverse)
desiredVel = desiredVel + moveDir
end
bv.Velocity = bv.Velocity * suspensionDamping + desiredVel * (1 - suspensionDamping)
rot.yaw = rot.yaw + yawVelocity
rot.roll = lerp(rot.roll, targetRoll, rollLerpSpeed)
pitchTilt = lerp(pitchTilt, targetPitch, pitchLerpSpeed)
bg.CFrame = calcRot(rot.yaw, pitchTilt, rot.roll)
end