Raycast hovercar bounces

So i have been scripting raycast hover cars and i ran into this weird problem

local Thusters = SuspensionCar.Thusters:GetChildren()
local Hitbox = SuspensionCar.Hitbox
local Force = Hitbox.BodyForce

local DamperHeight = 10
local Multipler = 0.01
local Weight = 0

local RaycastParameters = RaycastParams.new()
RaycastParameters.FilterDescendantsInstances = {SuspensionCar}
RaycastParameters.FilterType = Enum.RaycastFilterType.Blacklist

local Suspension = function()
    local Direction = Vector3.new(0, -1000, 0)
    local Raycast = workspace:Raycast(Hitbox.Position, Direction, RaycastParameters)
    
    if Raycast and Raycast.Instance.CanCollide then
        print(Raycast.Instance)
        local DistanceFromGround = (Hitbox.Position - Raycast.Position).Magnitude
        local PushUp = 1 + (DamperHeight - DistanceFromGround) * Multipler 
        
        Force.Force = Vector3.new(0, Hitbox:GetMass() * workspace.Gravity * PushUp, 0)
    else
        Force.Force = Vector3.new(0,0,0)
    end
    
end


local updateSuspension = coroutine.wrap(function()
    while wait() do
        Suspension()
    end
end)
updateSuspension()```

There are two problems that are causing this: first, because there is only a goal height and not a range of tolerance, the controller is always trying to compensate, resulting in oscillation. Second, even if there is a range of tolerance that the vehicle’s height can be, setting the force exactly equal the force of gravity on the vehicle does nothing to stop the inertia of the forces required to correct the vehicle’s position.

I’m not well-versed in physics, so this modified code will require some tweaking, particularly in regards to creating the force against inertia once the vehicle is already in range, but this should at least convey the idea of what needs to be done.

local Thusters = SuspensionCar.Thusters:GetChildren()
local Hitbox = SuspensionCar.Hitbox
local Force = Hitbox.BodyForce

local DamperHeight = 10
local HeightRange = 2	--Distance from DamperHeight that will be tolerated.
local Multipler = 0.01
local Weight = 0

local RaycastParameters = RaycastParams.new()
RaycastParameters.FilterDescendantsInstances = {SuspensionCar}
RaycastParameters.FilterType = Enum.RaycastFilterType.Blacklist

local Suspension = function()
	local Direction = Vector3.new(0, -1000, 0)
	local Raycast = workspace:Raycast(Hitbox.Position, Direction, RaycastParameters)

	if Raycast and Raycast.Instance.CanCollide then
		print(Raycast.Instance)
		local DistanceFromGround = (Hitbox.Position - Raycast.Position).Magnitude
		
		local PushUp
		local HeightDifference = DamperHeight - DistanceFromGround
		local AbsoluteDifference = math.abs(HeightDifference)
		if math.abs(HeightDifference) < HeightRange then
			--Vehicle is within tolerance. Current velocity needs to be canceled out.
			PushUp = 1 - (Hitbox.AssemblyLinearVelocity.Y * Multipler)
		else
			--Vehicle is out of tolerance. Forces must be applied to return to within tolerance.
			PushUp = 1 + (math.abs(AbsoluteDifference - HeightRange) * math.sign(HeightDifference) * Multipler)
		end
		
		Force.Force = Vector3.new(0, Hitbox:GetMass() * workspace.Gravity * PushUp, 0)
	else
		Force.Force = Vector3.new(0,0,0)
	end
end


local updateSuspension = coroutine.wrap(function()
	while wait() do
		Suspension()
	end
end)
updateSuspension()

I guess I should say as an aside: the height tolerance is perhaps unnecessary. The crux of solving the problem is compensating for both deviation in height and velocity. This could theoretically be done simultaneously to achieve a precise float height.

Less gooo tanks for the help it works perfectly :heart:

1 Like