Roblox · Гонки · урок 2
Своя машина: кузов, четыре колеса на пружинах, задний привод и руль. Садишься по E, едешь на WASD, выходишь прыжком — персонаж оказывается рядом с машиной.
Синим — что добавляем на этом уроке.
Workspace └─ Car (Model) — PrimaryPart = Body ├─ Body (Part) — кузов; масса 80–90 кг через Density │ └─ AttachmentFL, AttachmentFR, AttachmentBL, AttachmentBR (Attachment) — места крепления колёс, Orientation Z = 90 ├─ WheelFL, WheelFR, WheelBL, WheelBR (Part) — цилиндр-колесо; масса ≈ 60 кг │ ├─ Attachment (Attachment) │ ├─ CylindricalConstraint (CylindricalConstraint) — у задних — AngularActuatorType Motor │ ├─ SpringConstraint (SpringConstraint) — амортизатор │ └─ Decal (Decal) — диск колеса └─ VehicleSeat (VehicleSeat) — MaxSpeed, Torque, TurnSpeed ├─ WeldConstraint (WeldConstraint) — Part0 — сиденье, Part1 — Body ├─ ProximityPrompt (ProximityPrompt) — «Сесть» ├─ Attachment (Attachment) — точка выхода — сбоку от машины └─ Prompt (Script) ServerScriptService └─ Network (Script) StarterPlayer └─ StarterCharacterScripts └─ CarController (LocalScript)
Где: ServerScriptService · Script
Зачем: Когда игрок садится за руль, передаёт его компьютеру физику машины.
-- игрок зашёл в игру
game.Players.PlayerAdded:Connect(function(player)
-- у игрока появился персонаж
player.CharacterAdded:Connect(function(character)
-- персонаж сел или встал
character.Humanoid.Seated:Connect(function(active, seatPart)
-- встал — ничего не делаем
if seatPart == nil then return end
-- сел не за руль машины
if seatPart.Name ~= "VehicleSeat" then return end
-- физику машины считает компьютер водителя — управление без задержек
seatPart:SetNetworkOwner(player)
-- конец обработчика
end)
-- конец обработчика
end)
-- конец обработчика
end)Где: StarterPlayer → StarterCharacterScripts · LocalScript
Зачем: Читает руль и газ сиденья и крутит колёса; при выходе ставит персонажа рядом с машиной.
-- персонаж игрока (скрипт лежит в StarterCharacterScripts)
local character = script.Parent
-- плавные изменения
local TS = game:GetService("TweenService")
-- поворот колёс за полсекунды
local tweenInfo = TweenInfo.new(0.5)
-- подписка на руль и газ, пока сидим в машине
local connection = nil
-- точка, куда переносим при выходе
local exitAttach = nil
-- сел или встал
character.Humanoid.Seated:Connect(function(active, seatPart)
-- была старая подписка
if connection ~= nil then
-- отключаем
connection:Disconnect()
-- забываем
connection = nil
-- конец проверки
end
-- встал с сиденья
if seatPart == nil then
-- вышли из машины
if exitAttach ~= nil then
-- ставим персонажа рядом с машиной
character:PivotTo(exitAttach.WorldCFrame)
-- забываем точку
exitAttach = nil
-- конец проверки
end
-- дальше — только для тех, кто сел
return
-- конец проверки
end
-- сел не за руль
if seatPart.Name ~= "VehicleSeat" then return end
-- точка выхода внутри сиденья
exitAttach = seatPart:FindFirstChildOfClass("Attachment")
-- модель машины
local car = seatPart.Parent
-- крепление переднего левого колеса
local attachFL = car.PrimaryPart.AttachmentFL
-- крепление переднего правого колеса
local attachFR = car.PrimaryPart.AttachmentFR
-- мотор заднего левого колеса
local cylindricalBL = car.WheelBL.CylindricalConstraint
-- мотор заднего правого колеса
local cylindricalBR = car.WheelBR.CylindricalConstraint
-- скорость вращения колеса = скорость ÷ радиус
local maxAngVelocity = seatPart.MaxSpeed / (car.WheelBR.Size.Y / 2)
-- у сиденья поменялось свойство
connection = seatPart.Changed:Connect(function(property)
-- руль: A/D или стрелки
if property == "SteerFloat" then
-- угол поворота передних колёс
local orientation = Vector3.new(0, -seatPart.SteerFloat * seatPart.TurnSpeed, 90)
-- плавно поворачиваем левое
TS:Create(attachFL, tweenInfo, {Orientation = orientation}):Play()
-- и правое
TS:Create(attachFR, tweenInfo, {Orientation = orientation}):Play()
-- газ: W/S
elseif property == "ThrottleFloat" then
-- сила мотора при газе
local torque = math.abs(seatPart.ThrottleFloat) * seatPart.Torque
-- отпустили газ — небольшая сила, машина плавно тормозит
if torque == 0 then torque = 2000 end
-- сила левого мотора
cylindricalBL.MotorMaxTorque = torque
-- сила правого мотора
cylindricalBR.MotorMaxTorque = torque
-- вперёд, назад или стоп
local angVelocity = math.sign(seatPart.ThrottleFloat) * maxAngVelocity
-- крутим левое колесо
cylindricalBL.AngularVelocity = angVelocity
-- крутим правое колесо
cylindricalBR.AngularVelocity = angVelocity
-- конец проверки
end
-- конец обработчика
end)
-- конец обработчика
end)Где: Workspace → Car → VehicleSeat · Script
Зачем: Сажает игрока за руль по E и прячет надпись, пока место занято.
-- сиденье водителя
local seatPart = script.Parent
-- надпись «Сесть» (клавиша E)
local prompt = seatPart.ProximityPrompt
-- кто-то сел или вышел
seatPart:GetPropertyChangedSignal("Occupant"):Connect(function()
-- надпись видна, только когда место свободно
prompt.Enabled = seatPart.Occupant == nil
-- конец обработчика
end)
-- игрок нажал E
prompt.Triggered:Connect(function(player)
-- его персонаж
local humanoid = player.Character and player.Character:FindFirstChildOfClass("Humanoid")
-- персонаж есть
if humanoid then
-- сажаем за руль
seatPart:Sit(humanoid)
-- конец проверки
end
-- конец обработчика
end)Запусти Play (или Run) и убедись: