Roblox · Движение

Бег по стене

Прыгнул к стене из папки RunWalls, держишь «вперёд» — бежишь по стене 1,5 секунды, медленно сползая. Прыжок — отскок, можно перепрыгнуть на стену напротив.

Структура

Синим — что нужно создать.

StarterPlayer
└─ StarterPlayerScripts
   └─ WallRunLocal (LocalScript)
Workspace
└─ RunWalls (Folder) — стены для бега

Шаги

  1. Workspace → Folder «RunWalls», в неё длинные стены. Две стены параллельно на расстоянии ~12 studs — классическая паркур-полоса.
  2. StarterPlayerScripts → LocalScript «WallRunLocal».
  3. Как работает: в воздухе лучи вправо и влево ищут стену из RunWalls. Нашли и игрок жмёт вперёд — скорость вдоль стены, в сторону взгляда, с лёгким сползанием. 1,5 секунды — и срываешься; снова можно после приземления.
  4. Прыжок на стене (UserInputService.JumpRequest) отталкивает от стены вверх — время на новой стене считается заново.
  5. Скорость, время и сползание — SPEED, WALL_TIME и FALL в начале скрипта.

Скрипты

WallRunLocal

Где: StarterPlayer → StarterPlayerScripts · LocalScript
Зачем: Бег по стене и отскок.

-- события каждого кадра
local RunService = game:GetService("RunService")
-- прыжок
local UIS = game:GetService("UserInputService")
-- этот игрок
local player = game.Players.LocalPlayer
-- стены для бега
local runWalls = workspace:WaitForChild("RunWalls")
-- сколько секунд можно бежать по одной стене
local WALL_TIME = 1.5
-- скорость бега по стене
local SPEED = 28
-- как быстро сползаешь вниз
local FALL = 3
-- настройки луча
local params = RaycastParams.new()
-- только список
params.FilterType = Enum.RaycastFilterType.Include
-- стены для бега
params.FilterDescendantsInstances = {runWalls}
-- бежим по стене?
local running = false
-- когда начали
local started = 0
-- устали — до приземления по стенам не бегаем
local tired = false
-- в какую сторону смотрит стена
local wallNormal = nil

-- игрок нажал прыжок
UIS.JumpRequest:Connect(function()
    -- не на стене
    if not running then return end
    -- центр персонажа
    local root = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
    -- нет
    if not root then return end
    -- отскок от стены вверх — можно на соседнюю
    root.AssemblyLinearVelocity = wallNormal * 35 + Vector3.new(0, 40, 0)
    -- со стены спрыгнули
    running = false
    -- на следующей стене — новый отсчёт
    started = 0
-- конец обработчика
end)

-- каждый кадр
RunService.Heartbeat:Connect(function()
    -- персонаж
    local character = player.Character
    -- Humanoid
    local humanoid = character and character:FindFirstChildOfClass("Humanoid")
    -- центр
    local root = character and character:FindFirstChild("HumanoidRootPart")
    -- нет персонажа
    if not humanoid or not root or humanoid.Health <= 0 then return end
    -- стоит на земле
    if humanoid.FloorMaterial ~= Enum.Material.Air then
        -- не бежит по стене
        running = false
        -- отдохнул
        tired = false
        -- дальше не нужно
        return
    -- конец проверки
    end
    -- устал или не жмёт вперёд
    if tired or humanoid.MoveDirection.Magnitude < 0.1 then
        -- падает
        running = false
        -- дальше не нужно
        return
    -- конец проверки
    end
    -- вправо по земле
    local right = root.CFrame.RightVector * Vector3.new(1, 0, 1)
    -- стена справа или слева
    local result = workspace:Raycast(root.Position, right.Unit * 2.5, params) or workspace:Raycast(root.Position, -right.Unit * 2.5, params)
    -- стены сбоку нет
    if not result then
        -- падает
        running = false
        -- дальше не нужно
        return
    -- конец проверки
    end
    -- только что прыгнул на стену
    if not running then
        -- бежим
        running = true
        -- засекаем время
        if started == 0 then started = os.clock() end
    -- конец проверки
    end
    -- время вышло
    if os.clock() - started > WALL_TIME then
        -- срываемся
        running = false
        -- до приземления больше нельзя
        tired = true
        -- сброс
        started = 0
        -- дальше не нужно
        return
    -- конец проверки
    end
    -- запоминаем стену — для отскока
    wallNormal = result.Normal
    -- направление вдоль стены
    local along = result.Normal:Cross(Vector3.yAxis)
    -- в ту сторону, куда смотрим
    if along:Dot(root.CFrame.LookVector) < 0 then along = -along end
    -- бежим вдоль, прижимаемся, медленно сползаем
    root.AssemblyLinearVelocity = along * SPEED - result.Normal * 2 + Vector3.new(0, -FALL, 0)
-- конец обработчика
end)

Проверка

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

Собрать бег по стене одной командой