# Raycasting Suspension Scripting Help

Hi All,

I am trying to make a raycasting suspension system for a car.

After seeing this video, I decided to give raycast suspension a try because it suits my needs - Space Dust Racing UE4 Arcade Vehicle Physics Tour - YouTube

In my initial attempt at creating the raycast suspension, the “vehicle” (currently just a part) does float but it rocks (tilts & slides) back and forth.

After some further searching, I found this link where Oseday shares his suspension mathematics - Car Suspension (Scripted) - #5 by Kampfkarren

Unfortunately, I don’t really understand the math. I tried my best to implement it, but it still doesn’t balance and bounces up and down.

All assistance is appreciated, thanks in advance.

``````local d = 1 -- Suspension length?
local a = 1.8 --Stiffness, higher means higher height at suspension
local b = 0.6 --Rigidity higher means the suspensions will get less effected by slight changes and will balance out unlike Roblox's suspensions. This is the part that dampens the suspension.

local RunService = game:GetService("RunService")

local ST = {dx=0,d2x=0} --For storing the derivatives per suspension

local body = script.Parent

-- Initialise suspension force

local backLeftBodyThrust = Instance.new("BodyThrust")
backLeftBodyThrust.Name = "BackLeftBodyThrust"
backLeftBodyThrust.Location = Vector3.new(body.size.X/2, body.size.Y/2, body.size.Z/2)
backLeftBodyThrust.Parent = body

local backRightBodyThrust = Instance.new("BodyThrust")
backRightBodyThrust.Name = "BackRightBodyThrust"
backRightBodyThrust.Location = Vector3.new(-body.size.X/2, body.size.Y/2, body.size.Z/2)
backRightBodyThrust.Parent = body

local frontLeftBodyThrust = Instance.new("BodyThrust")
frontLeftBodyThrust.Name = "FrontLeftBodyThrust"
frontLeftBodyThrust.Location = Vector3.new(body.size.X/2, body.size.Y/2, -body.size.Z/2)
frontLeftBodyThrust.Parent = body

local frontRightBodyThrust = Instance.new("BodyThrust")
frontRightBodyThrust.Name = "FrontRightBodyThrust"
frontRightBodyThrust.Location = Vector3.new(-body.size.X/2, body.size.Y/2, -body.size.Z/2)
frontRightBodyThrust.Parent = body

RunService.Heartbeat:Connect(function()

local corners = {
backLeftCorner = body.Position - Vector3.new(body.size.X/2, 0, body.size.Z/2),
backRightCorner = body.Position - Vector3.new(-body.size.X/2, 0, body.size.Z/2),
frontLeftCorner = body.Position - Vector3.new(body.size.X/2, 0, -body.size.Z/2),
frontRightCorner = body.Position - Vector3.new(-body.size.X/2, 0, -body.size.Z/2),
}

local forces = {

}

for i, corner in pairs(corners) do

local rayOrigin = corner
local rayDirection = Vector3.new(0,-100,0)

local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {body}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

local x

if raycastResult then
x = d-(corner - raycastResult.Position).Magnitude

local f = (a*x + b*(x-ST.dx) + b/2*(x-ST.d2x)) * body.Mass/2 --Use the equation

ST.d2x = ST.dx --Store the past values
ST.dx = x

table.insert(forces, Vector3.new(0,f,0))
--Wheel.Force = Vector3.new(0,-f,0)
end
end
print(forces)

backLeftBodyThrust.Force = forces[1]
backRightBodyThrust.Force = forces[2]
frontLeftBodyThrust.Force = forces[3]
frontRightBodyThrust.Force = forces[4]
end)``````
4 Likes

Hi Everyone,

Just as a little bit of an update, I have tried a slightly different equation however still experiencing the same issues. All assistance is appreciated.

``````local suspensionLength = 10
local stiffness = 6

local RunService = game:GetService("RunService")

local body = script.Parent

local suspensionDamping = 2*math.sqrt(stiffness)

-- Initialise suspension force

local backLeftBodyThrust = Instance.new("BodyThrust")
backLeftBodyThrust.Name = "BackLeftBodyThrust"
backLeftBodyThrust.Location = Vector3.new(body.size.X/2, body.size.Y/2, body.size.Z/2)
backLeftBodyThrust.Parent = body

local backRightBodyThrust = Instance.new("BodyThrust")
backRightBodyThrust.Name = "BackRightBodyThrust"
backRightBodyThrust.Location = Vector3.new(-body.size.X/2, body.size.Y/2, body.size.Z/2)
backRightBodyThrust.Parent = body

local frontLeftBodyThrust = Instance.new("BodyThrust")
frontLeftBodyThrust.Name = "FrontLeftBodyThrust"
frontLeftBodyThrust.Location = Vector3.new(body.size.X/2, body.size.Y/2, -body.size.Z/2)
frontLeftBodyThrust.Parent = body

local frontRightBodyThrust = Instance.new("BodyThrust")
frontRightBodyThrust.Name = "FrontRightBodyThrust"
frontRightBodyThrust.Location = Vector3.new(-body.size.X/2, body.size.Y/2, -body.size.Z/2)
frontRightBodyThrust.Parent = body

local previousMagnitude = {0}

RunService.Heartbeat:Connect(function(delta)

-- calculate position of corners

local corners = {
backLeftCorner = body.Position - Vector3.new(body.size.X/2, 0, body.size.Z/2),
backRightCorner = body.Position - Vector3.new(-body.size.X/2, 0, body.size.Z/2),
frontLeftCorner = body.Position - Vector3.new(body.size.X/2, 0, -body.size.Z/2),
frontRightCorner = body.Position - Vector3.new(-body.size.X/2, 0, -body.size.Z/2),
}

local magnitude = {}

-- Create raycast originating from each corner

for i, corner in pairs(corners) do

local rayOrigin = corner
local rayDirection = Vector3.new(0,-100,0)

local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {body}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

-- if result send length return length of ray

if raycastResult then
if (corner - raycastResult.Position).Magnitude <= suspensionLength then
table.insert(magnitude, (corner - raycastResult.Position).Magnitude)
else
table.insert(magnitude, suspensionLength)
end
end
end

if magnitude[1] then

if previousMagnitude[1] ~= 0 then
backLeftBodyThrust.Force = Vector3.new(0, (-(magnitude[1] - suspensionLength)*stiffness-(suspensionDamping*(magnitude[1]-previousMagnitude[1])/delta))*body.Mass, 0)
backRightBodyThrust.Force = Vector3.new(0, (-(magnitude[2] - suspensionLength)*stiffness-(suspensionDamping*(magnitude[2]-previousMagnitude[2])/delta))*body.Mass, 0)
frontLeftBodyThrust.Force = Vector3.new(0, (-(magnitude[3] - suspensionLength)*stiffness-(suspensionDamping*(magnitude[3]-previousMagnitude[3])/delta))*body.Mass, 0)
frontRightBodyThrust.Force = Vector3.new(0, (-(magnitude[4] - suspensionLength)*stiffness-(suspensionDamping*(magnitude[4]-previousMagnitude[4])/delta))*body.Mass, 0)
end

previousMagnitude = magnitude

end

return(magnitude)
end)``````
2 Likes

CarSuspension2.rbxm (7.2 KB)

As a bit of an update I have attached my latest attempt as a roblox model.

I have multiplied the mass by gravity and divided by 4 (the number of thrusters). However, now it’s just bouncing up and down chaotically.

2 Likes

This raycasts suspension might help : https://www.youtube.com/watch?v=WSxGsKypFCw&t=452s

1 Like