You can write your topic however you want, but you need to answer these questions:
- What do you want to achieve? Keep it simple and clear!
I want to help stabilize my Scripted Suspension car. Keep it planted down on the ground when turning or going over terrain but so it can still go in the air
- What is the issue? Include screenshots / videos if possible!
Im not sure how to do this i am using modified version of the Jeep Suspension.
What i want is. But dont know how to make
What I have right now:
- What solutions have you tried so far? Did you look for solutions on the Developer Hub?
After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!
CarScript “Script”.
local car = script.Parent
local stats = car.Configurations
local Raycast = require(script.RaycastModule)
local Mass = 0
for i, v in pairs(car:GetChildren()) do
if v:IsA("BasePart") then
Mass = Mass + (v:GetMass() * 196.2)
end
end
local bodyPosition = car.Engine.BodyPosition
local bodyGyro = car.Engine.BodyGyro
--local bodyPosition = Instance.new("BodyPosition", car.Engine)
--bodyPosition.MaxForce = Vector3.new()
--local bodyGyro = Instance.new("BodyGyro", car.Engine)
--bodyGyro.MaxTorque = Vector3.new()
local function UpdateThrust(Thrust)
-- Raycasting
local hit, position = Raycast.new(Thrust.Position, Thrust.CFrame:vectorToWorldSpace(Vector3.new(0, -1, 0)) * stats.Height.Value) --game.Workspace:FindPartOnRay(ray, car)
local ThrustHeight = (position - Thrust.Position).magnitude
-- Wheel
local Weld = Thrust:FindFirstChild("Weld")
Weld.C0 = CFrame.new(0, -math.min(ThrustHeight, stats.Height.Value * 0.8) + (Weld.Part1.Size.Y / 2), 0)
-- Wheel turning
local offset = car.Engine.CFrame:inverse() * Thrust.CFrame
local speed = car.Engine.CFrame:vectorToObjectSpace(car.Engine.Velocity)
if offset.Z < 0 then
local direction = 1
if speed.Z > 0 then
direction = -1
end
Weld.C0 = Weld.C0 * CFrame.Angles(0, (car.Engine.RotVelocity.Y / 2) * direction, 0)
end
end
car.DriveSeat.Changed:connect(function(property)
if property == "Occupant" then
if car.DriveSeat.Occupant then
local player = game.Players:GetPlayerFromCharacter(car.DriveSeat.Occupant.Parent)
if player then
car.DriveSeat:SetNetworkOwner(player)
local localCarScript = script.LocalCarScript:Clone()
localCarScript.Parent = player.PlayerGui
localCarScript.Car.Value = car
localCarScript.Disabled = false
end
end
end
end)
--spawn(function()
while true do
game:GetService("RunService").Stepped:wait()
for i, part in pairs(car:GetChildren()) do
if part.Name == "Thrust" then
UpdateThrust(part)
end
end
if car.DriveSeat.Occupant then
bodyPosition.MaxForce = Vector3.new()
bodyGyro.MaxTorque = Vector3.new()
else
local hit, position, normal = Raycast.new(car.Engine.Position, car.Engine.CFrame:vectorToWorldSpace(Vector3.new(0, -1, 0)) * stats.Height.Value)
if hit and hit.CanCollide then
bodyPosition.MaxForce = Vector3.new(Mass / 5, math.huge, Mass / 5)
bodyPosition.Position = (CFrame.new(position, position + normal) * CFrame.new(0, 0, -stats.Height.Value + 0.5)).p
bodyGyro.MaxTorque = Vector3.new(math.huge, 0, math.huge)
bodyGyro.CFrame = CFrame.new(position, position + normal) * CFrame.Angles(-math.pi/2, 0, 0)
else
bodyPosition.MaxForce = Vector3.new()
bodyGyro.MaxTorque = Vector3.new()
end
end
end
--end)
LocalCarScript “LocalScript”
--local camera = game.Workspace.CurrentCamera
local player = game.Players.LocalPlayer
local character = player.Character
local humanoidRootPart = character.HumanoidRootPart
local car = script:WaitForChild("Car").Value
local stats = car:WaitForChild("Configurations")
local Raycast = require(car.CarScript.RaycastModule)
--local cameraType = Enum.CameraType.Follow
local movement = Vector2.new()
local gamepadDeadzone = 0.14
car.DriveSeat.Changed:connect(function(property)
if property == "Steer" then
movement = Vector2.new(car.DriveSeat.Steer, movement.Y)
elseif property == "Throttle" then
movement = Vector2.new(movement.X, car.DriveSeat.Throttle)
end
end)
-- Input begin
--game:GetService("UserInputService").InputBegan:connect(function(inputObject, gameProcessedEvent)
-- if not gameProcessedEvent then
-- if inputObject.KeyCode == Enum.KeyCode.W then
-- movement = Vector2.new(movement.X, 1)
-- elseif inputObject.KeyCode == Enum.KeyCode.A then
-- movement = Vector2.new(-1, movement.Y)
-- elseif inputObject.KeyCode == Enum.KeyCode.S then
-- movement = Vector2.new(movement.X, -1)
-- elseif inputObject.KeyCode == Enum.KeyCode.D then
-- movement = Vector2.new(1, movement.Y)
-- end
-- end
--end)
--
--game:GetService("UserInputService").InputChanged:connect(function(inputObject, gameProcessedEvent)
-- --if not gameProcessedEvent then
-- if inputObject.KeyCode == Enum.KeyCode.Thumbstick1 then
-- --Gamepad support because yay
-- if inputObject.Position.magnitude >= gamepadDeadzone then
-- movement = Vector2.new(movement.X, inputObject.Position.Y)
-- else
-- movement = Vector2.new(movement.X, 0)
-- end
-- elseif inputObject.KeyCode == Enum.KeyCode.Thumbstick2 then
-- if inputObject.Position.magnitude >= gamepadDeadzone then
-- movement = Vector2.new(inputObject.Position.X, movement.Y)
-- else
-- movement = Vector2.new(0, movement.Y)
-- end
-- end
-- --end
--end)
--
---- Input end
--game:GetService("UserInputService").InputEnded:connect(function(inputObject, gameProcessedEvent)
-- if inputObject.KeyCode == Enum.KeyCode.W then
-- if movement.Y == 1 then
-- movement = Vector2.new(movement.X, 0)
-- end
-- elseif inputObject.KeyCode == Enum.KeyCode.A then
-- if movement.X == -1 then
-- movement = Vector2.new(0, movement.Y)
-- end
-- elseif inputObject.KeyCode == Enum.KeyCode.S then
-- if movement.Y == -1 then
-- movement = Vector2.new(movement.X, 0)
-- end
-- elseif inputObject.KeyCode == Enum.KeyCode.D then
-- if movement.X == 1 then
-- movement = Vector2.new(0, movement.Y)
-- end
-- end
--end)
local force = 0
local damping = 0
local Mass = 0
for i, v in pairs(car:GetChildren()) do
if v:IsA("BasePart") then
Mass = Mass + (v:GetMass() * 196.2)
end
end
force = Mass * stats.Suspension.Value
damping = force / stats.Bounce.Value
local bodyVelocity = Instance.new("BodyVelocity", car.Engine)
bodyVelocity.velocity = Vector3.new(0, 0, 0)
bodyVelocity.maxForce = Vector3.new(0, 0, 0)
local bodyAngularVelocity = Instance.new("BodyAngularVelocity", car.Engine)
bodyAngularVelocity.angularvelocity = Vector3.new(0, 0, 0)
bodyAngularVelocity.maxTorque = Vector3.new(0, 0, 0)
local rotation = 0
local function UpdateThrust(Thrust)
--Make sure we have a bodythrust to move the wheel
local bodyThrust = Thrust:FindFirstChild("BodyThrust")
if not bodyThrust then
bodyThrust = Instance.new("BodyThrust", Thrust)
end
--Do some raycasting to get the height of the wheel
local hit, position = Raycast.new(Thrust.Position, Thrust.CFrame:vectorToWorldSpace(Vector3.new(0, -1, 0)) * stats.Height.Value)
local ThrustHeight = (position - Thrust.Position).magnitude
if hit and hit.CanCollide then
--If we're on the ground, apply some forces to push the wheel up
bodyThrust.force = Vector3.new(0, ((stats.Height.Value - ThrustHeight)^2) * (force / stats.Height.Value^2), 0)
local ThrustDamping = Thrust.CFrame:toObjectSpace(CFrame.new(Thrust.Velocity + Thrust.Position)).p * damping
bodyThrust.force = bodyThrust.force - Vector3.new(0, ThrustDamping.Y, 0)
else
bodyThrust.force = Vector3.new(0, 0, 0)
end
--Wheels
local Weld = Thrust:FindFirstChild("Weld")
if Weld then
Weld.C0 = CFrame.new(0, -math.min(ThrustHeight, stats.Height.Value * 0.8) + (Weld.Part1.Size.Y / 2), 0)
-- Wheel turning
local offset = car.Engine.CFrame:inverse() * Thrust.CFrame
local speed = car.Engine.CFrame:vectorToObjectSpace(car.Engine.Velocity)
if offset.Z < 0 then
local direction = 1
if speed.Z > 0 then
direction = -1
end
Weld.C0 = Weld.C0 * CFrame.Angles(0, (car.Engine.RotVelocity.Y / 2) * direction, 0)
end
Weld.C0 = Weld.C0 * CFrame.Angles(rotation, 0, 0)
end
end
--A simple function to check if the car is grounded
local function IsGrounded()
local hit, position = Raycast.new((car.Engine.CFrame * CFrame.new(0, 0, (car.Engine.Size.Z / 2) - 1)).p, car.Engine.CFrame:vectorToWorldSpace(Vector3.new(0, -1, 0)) * (stats.Height.Value + 0.2))
if hit and hit.CanCollide then
return(true)
end
return(false)
end
--local oldCameraType = camera.CameraType
--camera.CameraType = cameraType
--spawn(function()
while game:GetService("RunService").Heartbeat:wait() and car:FindFirstChild("DriveSeat") and character.Humanoid.SeatPart == car.DriveSeat do
--game:GetService("RunService").RenderStepped:wait()
if IsGrounded() then
if movement.Y ~= 0 then
local velocity = humanoidRootPart.CFrame.lookVector * movement.Y * stats.Speed.Value
humanoidRootPart.Velocity = humanoidRootPart.Velocity:Lerp(velocity, 0.1)
bodyVelocity.maxForce = Vector3.new(0, 0, 0)
else
bodyVelocity.maxForce = Vector3.new(Mass / 2, Mass / 4, Mass / 2)
end
local rotVelocity = humanoidRootPart.CFrame:vectorToWorldSpace(Vector3.new(movement.Y * stats.Speed.Value / 50, 0, -humanoidRootPart.RotVelocity.Y * 5 * movement.Y))
local speed = -humanoidRootPart.CFrame:vectorToObjectSpace(humanoidRootPart.Velocity).unit.Z
rotation = rotation + math.rad((-stats.Speed.Value / 5) * movement.Y)
if math.abs(speed) > 0.1 then
rotVelocity = rotVelocity + humanoidRootPart.CFrame:vectorToWorldSpace((Vector3.new(0, -movement.X * speed * stats.TurnSpeed.Value, 0)))
bodyAngularVelocity.maxTorque = Vector3.new(0, 0, 0)
else
bodyAngularVelocity.maxTorque = Vector3.new(Mass / 4, Mass / 2, Mass / 4)
end
humanoidRootPart.RotVelocity = humanoidRootPart.RotVelocity:Lerp(rotVelocity, 0.1)
--bodyVelocity.maxForce = Vector3.new(Mass / 3, Mass / 6, Mass / 3)
--bodyAngularVelocity.maxTorque = Vector3.new(Mass / 6, Mass / 3, Mass / 6)
else
bodyVelocity.maxForce = Vector3.new(0, 0, 0)
bodyAngularVelocity.maxTorque = Vector3.new(0, 0, 0)
end
for i, part in pairs(car:GetChildren()) do
if part.Name == "Thrust" then
UpdateThrust(part)
end
end
end
for i, v in pairs(car:GetChildren()) do
if v:FindFirstChild("BodyThrust") then
v.BodyThrust:Destroy()
end
end
bodyVelocity:Destroy()
bodyAngularVelocity:Destroy()
--camera.CameraType = oldCameraType
script:Destroy()
--end)
RayCasyModule “ModuleScript”.
local module = {}
function module.new(startPosition, startDirection)
local maxDistance = startDirection.magnitude
local direction = startDirection.unit
local lastPosition = startPosition
local distance = 0
local ignore = {}
local hit, position, normal
repeat
local ray = Ray.new(lastPosition, direction * (maxDistance - distance))
hit, position, normal = game.Workspace:FindPartOnRayWithIgnoreList(ray, ignore, false, true)
if hit then
if not hit.CanCollide then
table.insert(ignore, hit)
end
end
distance = (startPosition - position).magnitude
lastPosition = position
until distance >= maxDistance - 0.1 or (hit and hit.CanCollide)
return hit, position, normal
end
return module
Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.
So if anyone can help me do this it would be great so thanks.
THIS IS THE BASEPLATE!
Baseplate.rbxl (70.2 KB)