Hello everyone, I have recently built a spherecast suspension system. The problem is, it appears to be unstable and jittery. All of the calculations and VectorForce.Force setting is being done on the client script. The player currently has networkownership over the car. I would like to receive some advice or suggestions on fixing this issue, I am very stumped as of now.
Here is a clip of the jittering:
My ServerScript:
local RunService = game:GetService(‘RunService’)
local RepStorage = game:GetService(‘ReplicatedStorage’)
local Players = game:GetService(‘Players’)
local gizmo = require(RepStorage.gizmo)
local utils = require(script.Utils)
Players.PlayerAdded:Connect(function(plr)
print('Player', plr.Name, 'has been assigned NetworkOwnership.')
workspace.Chassis.PrimaryPart:SetNetworkOwner(plr)
end)
My ClientScript:
local RunService = game:GetService('RunService')
local RepStorage = game:GetService('ReplicatedStorage')
local gizmo = require(RepStorage.gizmo)
local utils = require(script.Utils)
local Vehicle = workspace.Chassis
local Chassis = Vehicle.PrimaryPart
local SuspensionPoints = utils.Init()
local MaxLength = 5
local MinLength = 1
local RestLength = 3.5
local WheelRadius = 2
local Stiffness = 100000
local Damping = 3000
local mu_static = 0.8
local mu_kinetic = 0.6
local FrictionrollingThreshold = 40
local SuspensionrollingThreshold = 60
local Rayparams = RaycastParams.new()
Rayparams.FilterType = Enum.RaycastFilterType.Exclude
Rayparams.FilterDescendantsInstances = {Chassis}
workspace:SetAttribute("GizmosEnabled", true)
RunService.Stepped:Connect(function(time, dt)
for _, attachment in ipairs(Chassis:GetChildren()) do
if SuspensionPoints[attachment.Name] then
local VectorForce = attachment.VectorForce
local Rayhit = workspace:Spherecast(attachment.WorldPosition, WheelRadius, -attachment.WorldCFrame.UpVector * MaxLength, Rayparams)
if Rayhit then
gizmo.drawRay(attachment.WorldPosition, -attachment.WorldCFrame.UpVector * Rayhit.Distance)
local SpringForce = Stiffness * (RestLength - Rayhit.Distance)
local velocity = (Rayhit.Distance - SuspensionPoints[attachment.Name]['prevLength']) / dt
local DampingForce = -Damping * velocity
local angle = math.acos(Rayhit.Normal:Dot(Vector3.new(0,1,0))) * (180 / math.pi)
local NetSpringForce
if angle < SuspensionrollingThreshold then
NetSpringForce = math.max(0, SpringForce + DampingForce)
else
NetSpringForce = 0
end
local NormalForce = (workspace.Gravity * Chassis.AssemblyMass * Rayhit.Normal:Dot(Vector3.new(0,1,0))) / 4
local maxStaticFriction = mu_static * NormalForce
local kineticFriction = mu_kinetic * NormalForce
local SidewaysVelocity = Chassis.AssemblyLinearVelocity:Dot(Chassis.CFrame.RightVector)
local TractionForce
if angle < FrictionrollingThreshold then
if math.abs(SidewaysVelocity) > 0.1 then
TractionForce = kineticFriction * -SidewaysVelocity
else
TractionForce = math.min(SidewaysVelocity, maxStaticFriction) * -SidewaysVelocity
end
else
TractionForce = 0
end
VectorForce.Force = Vector3.new(TractionForce, NetSpringForce, 0)
else
gizmo.drawRay(attachment.WorldPosition, -attachment.WorldCFrame.UpVector * MaxLength)
VectorForce.Force = Vector3.zero
end
SuspensionPoints[attachment.Name]['prevLength'] = Rayhit and Rayhit.Distance or MaxLength
end
end
end)
It would be very nice if I am able to receive assistance in solving this issue, please feel free to let me know if I missed out on any details and I will gladly clarify. Thanks!