I currently have a hoverbike, however, I want it to be able to go up wedges and other slopes. I thought about raycasting below the bike to determine the slope and then update the orientation of the bike, however, that would only work for parts and not terrain slopes (I think). Is there a different way I should go about this?
Current bike functionality: https://cdn.discordapp.com/attachments/779571552102383706/1114698014058090576/2023-06-03_18-28-34.mp4
Code:
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local settings = {
height = 2,
reverse = true,
speed = 50,
rev = -10,
acceleration = 0.3,
deceleration = 0.5,
turn = 2,
force = 4000000,
}
local Speeder = script.Parent
local Seat = Speeder:WaitForChild("VehicleSeat")
local BodyPosition = Seat:FindFirstChildOfClass("BodyPosition")
local BodyGyro = Seat:FindFirstChildOfClass("BodyGyro")
local BodyVelocity = Seat:FindFirstChildOfClass("BodyVelocity")
local ProximityPrompt = Seat:FindFirstChildOfClass("Attachment").ProximityPrompt
local Headlight = Speeder:WaitForChild("Headlight").SurfaceLight
local Animation = Instance.new("Animation")
Animation.AnimationId = "rbxassetid://13640690698"
local float = 0.25
local speed = 0
local height = settings.height
local connection
local tween
local track
local function cast(first: CFrame, second: CFrame, ignore: any, distance: number)
local ray = Ray.new(first.Position, (second.Position - first.Position).Unit * distance)
local object, position = workspace:FindPartOnRay(ray, ignore)
return workspace:FindPartOnRay(ray, ignore)
end
local function cleanup()
if connection then
connection:Disconnect()
connection = nil
end
if tween then
tween:Cancel()
tween = nil
end
if track then
track:Stop()
track = nil
end
end
Seat:GetPropertyChangedSignal("Occupant"):Connect(function()
local occupant = Seat.Occupant
if occupant then
local animator = occupant:FindFirstChildOfClass("Animator")
if (not animator) then
return
end
cleanup()
track = animator:LoadAnimation(Animation)
track.Looped = true
track:Play()
Seat.Anchored = false
Headlight.Enabled = true
ProximityPrompt.Enabled = false
BodyVelocity.MaxForce = Vector3.new(100000,0,100000)
connection = RunService.Stepped:Connect(function()
local emit = Seat.CFrame * CFrame.new(0,-1,-4)
local object, position = cast(emit,emit * CFrame.new(0,-100,0), Speeder, settings.height)
if object then
BodyPosition.Position = Vector3.new(position.X,position.Y + settings.height,position.Z)
BodyPosition.MaxForce = Vector3.new(0,40000000,0)
else
BodyPosition.MaxForce = Vector3.new(0,0,0)
end
if Seat.Throttle == 1 then
if speed + settings.acceleration > settings.speed then
speed = settings.speed
elseif speed + settings.acceleration <= settings.speed then
speed = speed + settings.acceleration
end
elseif Seat.Throttle == -1 then
if speed - settings.deceleration > 0 then
speed = speed - settings.deceleration
elseif speed - settings.deceleration <= 0 then
if settings.reverse == true then
if speed - settings.deceleration > settings.rev then
speed = speed - settings.deceleration
elseif speed - settings.deceleration <= settings.rev then
speed = settings.rev
end
speed = speed - settings.deceleration
else
speed = 1
end
end
end
if Seat.Steer == 1 then
BodyGyro.CFrame = BodyGyro.CFrame * CFrame.Angles(0,-0.05,0)
elseif Seat.Steer == -1 then
BodyGyro.CFrame = BodyGyro.CFrame * CFrame.Angles(0,0.05,0)
end
BodyVelocity.Velocity = Seat.CFrame.lookVector * speed
end)
else
Seat.Anchored = true
Headlight.Enabled = false
ProximityPrompt.Enabled = true
BodyVelocity.MaxForce = Vector3.new(0,0,0)
BodyPosition.MaxForce = Vector3.new(40000000,40000000,40000000)
cleanup()
connection = RunService.Heartbeat:Connect(function()
if tween then
return
end
if float == 0.25 then
float = -0.25
else
float = 0.25
end
tween = TweenService:Create(Seat,TweenInfo.new(2,Enum.EasingStyle.Sine,Enum.EasingDirection.InOut),{CFrame = Seat.CFrame + Vector3.new(0,float,0)})
tween:Play()
tween.Completed:Connect(function()
tween = nil
end)
end)
end
end)
ProximityPrompt.Triggered:Connect(function(player: Player)
if Seat.Occupant then
return
end
local character = player.Character
local humanoid = character:FindFirstChildOfClass("Humanoid")
if (not character) or (not humanoid) then
return
end
Seat:Sit(humanoid)
end)
connection = RunService.Heartbeat:Connect(function()
if tween then
return
end
if float == 0.25 then
float = -0.25
else
float = 0.25
end
tween = TweenService:Create(Seat,TweenInfo.new(2,Enum.EasingStyle.Sine,Enum.EasingDirection.InOut),{CFrame = Seat.CFrame + Vector3.new(0,float,0)})
tween:Play()
tween.Completed:Connect(function()
tween = nil
end)
end)