Roblox · 2D Раннер · урок 2

Бег, прыжок и препятствия

Своё управление: пробел — старт, дальше персонаж бежит сам, пробел — прыжок. На трассе — опасные препятствия и трамплины.

Структура

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

Workspace
├─ Kill (Folder) — все опасные препятствия
│  └─ Lava, Spikes, … (Part / Model) — детали или модели из деталей
└─ Trampoline (Model) — трамплин
   ├─ Frame (Part) — основание
   ├─ Pad (Part) — пружинящая поверхность; Anchored
   └─ Trampoline (Script)
ServerScriptService
└─ Killbrick (Script)
StarterPlayer
└─ StarterPlayerScripts
   ├─ CameraScript (LocalScript)
   └─ ControlScript (LocalScript)

Шаги

  1. StarterPlayer → StarterPlayerScripts → «+» → LocalScript «ControlScript».
  2. Как работает: стандартное управление выключено, персонаж стоит на якоре. Первый пробел (или тап на телефоне) снимает якорь и каждый кадр толкает персонажа в сторону минуса X. Следующие нажатия — прыжок. После смерти забег окончен, новый персонаж снова ждёт старта.
  3. Workspace → «+» → Folder «Kill». Всё, что убивает при касании (лава, шипы, пила), клади сюда. Препятствие из нескольких деталей — Model внутри Kill: скрипт находит детали и внутри моделей.
  4. ServerScriptService → «+» → Script «Killbrick».
  5. Совет: на стены, в которые персонаж может упереться и застрять, поставь невидимые детали (Transparency 1) в папку Kill — застрял, значит проиграл.
  6. Трамплин: Workspace → «+» → Model «Trampoline», внутри детали Frame (основание) и Pad (верх, Anchored). Выдели модель → PrimaryPart → Pad. В модель «+» → Script «Trampoline».
  7. Трамплин в яме даёт выбор: упасть и подпрыгнуть на нижний путь или перепрыгнуть яму по верхнему.

Скрипты

ControlScript

Где: StarterPlayer → StarterPlayerScripts · LocalScript
Зачем: Старт и прыжок по пробелу или тапу, бег — сам.

-- игрок на этом компьютере
local player = game.Players.LocalPlayer
-- события каждого кадра
local RunService = game:GetService("RunService")
-- клавиатура и экран
local UIS = game:GetService("UserInputService")
-- стандартные скрипты управления
local PlayerModule = require(player:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule"))
-- персонаж, которым управляем
local humanoid = nil
-- идёт ли забег
local gameStarted = false

-- выключаем WASD и стандартный прыжок — управляем сами
PlayerModule:GetControls():Disable()

-- забег окончен
local function StopRun()
    -- больше не бежим
    gameStarted = false
    -- перестаём толкать персонажа вперёд
    RunService:UnbindFromRenderStep("Move")
-- конец функции
end

-- новый персонаж
local function Setup(character)
    -- запоминаем его
    humanoid = character:WaitForChild("Humanoid")
    -- стоит на месте, пока не нажали старт
    character:WaitForChild("HumanoidRootPart").Anchored = true
    -- погиб — забег окончен
    humanoid.Died:Connect(StopRun)
-- конец функции
end

-- каждый новый персонаж
player.CharacterAdded:Connect(Setup)
-- персонаж уже появился до запуска скрипта
if player.Character then Setup(player.Character) end

-- нажали клавишу или тапнули — подписка одна на всю игру
UIS.InputBegan:Connect(function(input, gp)
    -- нажатие ушло в чат или на кнопку интерфейса
    if gp then return end
    -- пробел или тап по экрану телефона
    local pressed = input.KeyCode == Enum.KeyCode.Space or input.UserInputType == Enum.UserInputType.Touch
    -- другая клавиша
    if not pressed then return end
    -- персонажа нет или он погиб
    if not humanoid or humanoid.Health <= 0 then return end
    -- уже бежим
    if gameStarted then
        -- прыжок
        humanoid.Jump = true
    -- ещё стоим
    else
        -- старт
        gameStarted = true
        -- отпускаем персонажа
        humanoid.Parent.HumanoidRootPart.Anchored = false
        -- каждый кадр
        RunService:BindToRenderStep("Move", Enum.RenderPriority.Character.Value, function()
            -- бежим по оси X в сторону минуса
            humanoid:Move(Vector3.new(-1, 0, 0), false)
        -- конец функции кадра
        end)
    -- конец проверки
    end
-- конец обработчика
end)

Killbrick

Где: ServerScriptService · Script
Зачем: Убивает персонажа при касании любого препятствия из папки Kill.

-- папка со всеми опасными препятствиями
local killFolder = workspace:WaitForChild("Kill")

-- все детали, в том числе внутри моделей
for _, part in pairs(killFolder:GetDescendants()) do
    -- это деталь, а не папка или модель
    if part:IsA("BasePart") then
        -- детали что-то коснулось
        part.Touched:Connect(function(otherPart)
            -- модель, в которой коснувшаяся деталь
            local character = otherPart.Parent
            -- это персонаж?
            local humanoid = character:FindFirstChildOfClass("Humanoid")
            -- нет — пропускаем
            if not humanoid then return end
            -- персонаж погибает
            humanoid.Health = 0
        -- конец обработчика
        end)
    -- конец проверки
    end
-- конец перебора
end

Trampoline

Где: Workspace → Trampoline · Script
Зачем: Подбрасывает вверх всё, что встало на Pad.

-- пружинящая поверхность модели
local pad = script.Parent:WaitForChild("Pad")
-- сила подброса — подбери под свою яму
local POWER = 200

-- постоянно
while true do
    -- поверхность «толкает» вверх всё, что на неё встало
    pad.AssemblyLinearVelocity = pad.CFrame.UpVector * POWER
    -- пауза
    task.wait(0.1)
-- конец цикла
end

Проверка

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