Roblox · Песочница · урок 4

Навыки: бег, присед и полёт

Shift — бег, C — присесть, F — полёт: летишь туда, куда смотрит камера, пробел — вверх.

Структура

Синим — что добавляем на этом уроке.

StarterPlayer → StarterCharacterScripts
├─ Run (LocalScript) — внутри Animation «RunAnim» (ID можно не вставлять)
├─ Crouch (LocalScript) — внутри Animation «CrouchAnim» (ID можно не вставлять)
└─ Fly (LocalScript)

Шаги

  1. Бег и присед — LocalScript в StarterCharacterScripts. Внутри каждого обязательно Animation «RunAnim» и «CrouchAnim» — скрипт их ждёт; ID — свои анимации (приоритет Movement). Без них бег всё равно ускоряет, присед замедляет и опускает камеру.
  2. Скрипты не перебивают скорость друг друга: присел на бегу — бег прекратился.
  3. StarterPlayer → EnableMouseLockOption выкл., чтобы Shift не включал шифт-лок.
  4. Полёт — LocalScript «Fly». В методичке он был на пробеле и мешал прыжку, а BodyPosition и BodyGyro устарели. Здесь F, LinearVelocity (скорость) и AlignOrientation (поворот).
  5. В полёте W/A/S/D — относительно камеры: смотришь вверх и жмёшь W — летишь вверх. Пробел — просто вверх.

Скрипты

Run

Где: StarterPlayer → StarterCharacterScripts · LocalScript
Зачем: Бег на Shift.

-- клавиатура
local UIS = game:GetService("UserInputService")
-- скрипт лежит в персонаже
local character = script.Parent
-- Humanoid
local humanoid = character:WaitForChild("Humanoid")
-- проигрывает анимации
local animator = humanoid:WaitForChild("Animator")
-- скорость бега
local RUN_SPEED = 25
-- обычная скорость
local WALK_SPEED = 16

-- Animation внутри скрипта
local runAnim = script:WaitForChild("RunAnim")
-- дорожка анимации (если есть своя)
local runTrack = nil
-- ID вставлен
if runAnim.AnimationId ~= "" then
    -- загружаем
    runTrack = animator:LoadAnimation(runAnim)
    -- важнее обычной ходьбы
    runTrack.Priority = Enum.AnimationPriority.Movement
    -- по кругу
    runTrack.Looped = true
-- конец проверки
end
-- сейчас бежим?
local running = false

-- включает и выключает анимацию бега
local function UpdateAnim()
    -- своей анимации нет — бежим стандартной
    if not runTrack then return end
    -- персонаж двигается
    local moving = humanoid.MoveDirection.Magnitude > 0
    -- бежим, а анимация не играет
    if running and moving and not runTrack.IsPlaying then
        -- включаем плавно
        runTrack:Play(0.2)
    -- остановились
    elseif (not running or not moving) and runTrack.IsPlaying then
        -- выключаем
        runTrack:Stop(0.2)
    -- конец проверки
    end
-- конец функции
end

-- начать или закончить бег
local function SetRunning(value)
    -- погибшие не бегают
    if humanoid.Health <= 0 then return end
    -- сидим? (ставит скрипт приседания)
    local crouching = character:GetAttribute("Crouching")
    -- сидя не бегаем
    running = value and not crouching
    -- скоростью сидя управляет другой скрипт
    if not crouching then
        -- бег или шаг
        humanoid.WalkSpeed = running and RUN_SPEED or WALK_SPEED
    -- конец проверки
    end
    -- анимация
    UpdateAnim()
-- конец функции
end

-- нажали клавишу
UIS.InputBegan:Connect(function(input, processed)
    -- левый Shift, и не в чате
    if not processed and input.KeyCode == Enum.KeyCode.LeftShift then
        -- бежим
        SetRunning(true)
    -- конец проверки
    end
-- конец функции
end)
-- отпустили клавишу
UIS.InputEnded:Connect(function(input)
    -- это Shift
    if input.KeyCode == Enum.KeyCode.LeftShift then
        -- идём шагом
        SetRunning(false)
    -- конец проверки
    end
-- конец функции
end)
-- встали или пошли — обновляем анимацию
humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(UpdateAnim)
-- присели во время бега
character:GetAttributeChangedSignal("Crouching"):Connect(function()
    -- бег прекращается
    if character:GetAttribute("Crouching") then SetRunning(false) end
-- конец функции
end)

Crouch

Где: StarterPlayer → StarterCharacterScripts · LocalScript
Зачем: Присед на C.

-- клавиатура
local UIS = game:GetService("UserInputService")
-- персонаж
local character = script.Parent
-- Humanoid
local humanoid = character:WaitForChild("Humanoid")
-- анимации
local animator = humanoid:WaitForChild("Animator")
-- скорость сидя
local CROUCH_SPEED = 6
-- обычная скорость
local WALK_SPEED = 16

-- Animation внутри скрипта
local crouchAnim = script:WaitForChild("CrouchAnim")
-- дорожка анимации
local track = nil
-- своя анимация есть
if crouchAnim.AnimationId ~= "" then
    -- загружаем
    track = animator:LoadAnimation(crouchAnim)
    -- поверх ходьбы и стояния
    track.Priority = Enum.AnimationPriority.Action
    -- по кругу
    track.Looped = true
-- конец проверки
end
-- сидим?
local crouching = false

-- нажали клавишу
UIS.InputBegan:Connect(function(input, processed)
    -- нужна C и не в чате
    if processed or input.KeyCode ~= Enum.KeyCode.C then return end
    -- погибшие не приседают
    if humanoid.Health <= 0 then return end
    -- C переключает: сесть / встать
    crouching = not crouching
    -- сообщаем скрипту бега
    character:SetAttribute("Crouching", crouching)
    -- сели
    if crouching then
        -- медленно
        humanoid.WalkSpeed = CROUCH_SPEED
        -- камера ниже — видно и без анимации
        humanoid.CameraOffset = Vector3.new(0, -1.5, 0)
        -- анимация приседа
        if track then track:Play(0.2) end
    -- встали
    else
        -- обычная скорость
        humanoid.WalkSpeed = WALK_SPEED
        -- камера на место
        humanoid.CameraOffset = Vector3.zero
        -- выключаем анимацию
        if track then track:Stop(0.2) end
    -- конец проверки
    end
-- конец функции
end)

Fly

Где: StarterPlayer → StarterCharacterScripts · LocalScript
Зачем: Полёт на F.

-- клавиатура
local UIS = game:GetService("UserInputService")
-- каждый кадр
local RunService = game:GetService("RunService")
-- персонаж
local character = script.Parent
-- Humanoid
local humanoid = character:WaitForChild("Humanoid")
-- центр
local root = character:WaitForChild("HumanoidRootPart")
-- камера — летим туда, куда смотрим
local camera = workspace.CurrentCamera
-- F — взлететь / приземлиться
local KEY = Enum.KeyCode.F
-- скорость полёта
local SPEED = 40
-- летим?
local flying = false

-- точка для сил
local attachment = root:FindFirstChild("RootAttachment") or Instance.new("Attachment", root)
-- держит скорость полёта
local move = Instance.new("LinearVelocity")
-- за центр
move.Attachment0 = attachment
-- сильнее гравитации
move.MaxForce = 1000000
-- пока висим
move.VectorVelocity = Vector3.zero
-- выключено до полёта
move.Enabled = false
-- в персонажа
move.Parent = root
-- поворачивает персонажа
local turn = Instance.new("AlignOrientation")
-- к заданному направлению
turn.Mode = Enum.OrientationAlignmentMode.OneAttachment
-- за центр
turn.Attachment0 = attachment
-- жёстко
turn.RigidityEnabled = true
-- выключено до полёта
turn.Enabled = false
-- в персонажа
turn.Parent = root

-- включить или выключить полёт
local function SetFlying(value)
    -- запоминаем
    flying = value
    -- сила
    move.Enabled = value
    -- поворот
    turn.Enabled = value
    -- в полёте ноги не шагают
    humanoid.PlatformStand = value
-- конец функции
end

-- нажали
UIS.InputBegan:Connect(function(input, processed)
    -- F переключает
    if not processed and input.KeyCode == KEY and humanoid.Health > 0 then SetFlying(not flying) end
-- конец функции
end)
-- погиб — падает
humanoid.Died:Connect(function() SetFlying(false) end)

-- каждый кадр
RunService.RenderStepped:Connect(function()
    -- не летим
    if not flying then return end
    -- камера
    local cf = camera.CFrame
    -- направление
    local dir = Vector3.zero
    -- вперёд — куда смотрит камера (и вверх-вниз тоже)
    if UIS:IsKeyDown(Enum.KeyCode.W) then dir += cf.LookVector end
    -- назад
    if UIS:IsKeyDown(Enum.KeyCode.S) then dir -= cf.LookVector end
    -- вправо
    if UIS:IsKeyDown(Enum.KeyCode.D) then dir += cf.RightVector end
    -- влево
    if UIS:IsKeyDown(Enum.KeyCode.A) then dir -= cf.RightVector end
    -- пробел — вверх
    if UIS:IsKeyDown(Enum.KeyCode.Space) then dir += Vector3.new(0, 1, 0) end
    -- одинаковая скорость в любую сторону
    if dir.Magnitude > 0 then dir = dir.Unit end
    -- летим
    move.VectorVelocity = dir * SPEED
    -- куда смотрит камера по горизонтали
    local flat = Vector3.new(cf.LookVector.X, 0, cf.LookVector.Z)
    -- персонаж смотрит туда же
    if flat.Magnitude > 0.01 then turn.CFrame = CFrame.lookAt(Vector3.zero, flat) end
-- конец функции
end)

Проверка

Запусти Play (или Run) и убедись: