This is the thing I have so far: Jeep - Roblox.
Except I know nothing about physics so it’s really hard for me to accomplish the sliding effect. I’ve tried using formulas and putting them in the code, but I don’t think I’m doing it right, mostly my efforts are just guessing what goes where, which hasn’t gone to well for me. I kind of want the sliding effect when it turns to be like the basic roblox car/old roblox cars people used to make.
Any help would be appreciated.
Local script.
--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 --Total weight of the vehicle. Default: (27989)
--Calculate the total weight of the vehicle
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 --Default: (111959)
damping = force / stats.Bounce.Value --Default: (1119)
local bodyVelocity = Instance.new("BodyVelocity", car.Chassis)
bodyVelocity.velocity = Vector3.new(0, 0, 0)
bodyVelocity.maxForce = Vector3.new(0, 0, 0)
local bodyAngularVelocity = Instance.new("BodyAngularVelocity", car.Chassis)
bodyAngularVelocity.angularvelocity = Vector3.new(0, 0, 0)
bodyAngularVelocity.maxTorque = Vector3.new(0, 0, 0)
local rotation = 0
local function UpdateThruster(thruster)
--Make sure we have a bodythrust to move the wheel
local bodyThrust = thruster:FindFirstChild("BodyThrust")
if not bodyThrust then
bodyThrust = Instance.new("BodyThrust", thruster)
end
--Do some raycasting to get the height of the wheel
local hit, position = Raycast.new(thruster.Position, thruster.CFrame:vectorToWorldSpace(Vector3.new(0, -1, 0)) * stats.Height.Value)
local thrusterHeight = (position - thruster.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 - thrusterHeight)^2) * (force / stats.Height.Value^2), 0)
local thrusterDamping = thruster.CFrame:toObjectSpace(CFrame.new(thruster.Velocity + thruster.Position)).p * damping
bodyThrust.force = bodyThrust.force - Vector3.new(0, thrusterDamping.Y, 0)
else
bodyThrust.force = Vector3.new(0, 0, 0)
end
--Wheels
local wheelWeld = thruster:FindFirstChild("WheelWeld")
if wheelWeld then
wheelWeld.C0 = CFrame.new(0, -math.min(thrusterHeight, stats.Height.Value * 0.8) + (wheelWeld.Part1.Size.Y / 2), 0)
-- Wheel turning
local offset = car.Chassis.CFrame:inverse() * thruster.CFrame
local speed = car.Chassis.CFrame:vectorToObjectSpace(car.Chassis.Velocity)
if offset.Z < 0 then
local direction = 1
if speed.Z > 0 then
direction = -1
end
wheelWeld.C0 = wheelWeld.C0 * CFrame.Angles(0, (car.Chassis.RotVelocity.Y / 2) * direction, 0)
end
wheelWeld.C0 = wheelWeld.C0 * CFrame.Angles(rotation, 0, 0)
end
end
--A simple function to check if the car is grounded
local function IsGrounded()
--Start a raycast at the middle back - 1 stud forward, going downwards relative to the start point and orientation of the chassis part (so if slanted shoot downwards from the bottom of the surface)
local hit, position = Raycast.new((car.Chassis.CFrame * CFrame.new(0, 0, (car.Chassis.Size.Z / 2) - 1)).p, car.Chassis.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 --Check if the jeep is on the ground whether slanted or not
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) --Originally (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 == "Thruster" then
UpdateThruster(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)
Server 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.Chassis.BodyPosition
local bodyGyro = car.Chassis.BodyGyro
--local bodyPosition = Instance.new("BodyPosition", car.Chassis)
--bodyPosition.MaxForce = Vector3.new()
--local bodyGyro = Instance.new("BodyGyro", car.Chassis)
--bodyGyro.MaxTorque = Vector3.new()
local function UpdateThruster(thruster)
-- Raycasting
local hit, position = Raycast.new(thruster.Position, thruster.CFrame:vectorToWorldSpace(Vector3.new(0, -1, 0)) * stats.Height.Value) --game.Workspace:FindPartOnRay(ray, car)
local thrusterHeight = (position - thruster.Position).magnitude
-- Wheel
--local wheelWeld = thruster:FindFirstChild("WheelWeld")
--wheelWeld.C0 = CFrame.new(0, -math.min(thrusterHeight, stats.Height.Value * 0.8) + (wheelWeld.Part1.Size.Y / 2), 0)
-- Wheel turning
local offset = car.Chassis.CFrame:inverse() * thruster.CFrame
local speed = car.Chassis.CFrame:vectorToObjectSpace(car.Chassis.Velocity)
if offset.Z < 0 then
local direction = 1
if speed.Z > 0 then
direction = -1
end
--wheelWeld.C0 = wheelWeld.C0 * CFrame.Angles(0, (car.Chassis.RotVelocity.Y / 2) * direction, 0)
end
-- Particles
if hit and thruster.Velocity.magnitude >= 5 then
--wheelWeld.Part1.ParticleEmitter.Enabled = true
else
--wheelWeld.Part1.ParticleEmitter.Enabled = false
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 == "Thruster" then
UpdateThruster(part)
end
end
if car.DriveSeat.Occupant then
local ratio = car.DriveSeat.Velocity.magnitude / stats.Speed.Value
bodyPosition.MaxForce = Vector3.new()
bodyGyro.MaxTorque = Vector3.new()
else
local hit, position, normal = Raycast.new(car.Chassis.Position, car.Chassis.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)