Roblox · Обби · урок 7
Итог курса на одной странице: полная структура обби и финальные версии всех скриптов. Удобно сверить свою игру или собрать полосу заново.
Синим — что добавляем на этом уроке.
Workspace ├─ SpawnLocation (SpawnLocation) ├─ Obby (Model) — вся полоса │ ├─ Start, Platform… (Part) — платформы, Anchored │ ├─ Lava (Part) — лава под полосой — KillScript │ ├─ KillBrick (Part) — KillScript │ ├─ Step (Part) — DisappearScript │ ├─ MovingPlatform (Part) — MoveScript │ ├─ SpeedBrick, NormalBrick (Part) — SpeedScript, NormalSpeedScript │ ├─ Conveyor (Part) — ConveyorScript │ ├─ SpinBase → Motor, SpinBar (Part) — вращение на HingeConstraint │ └─ PendulumTop → Rope, Ball (Part) — маятник; в Ball — ResetScript ├─ Checkpoints (Folder) │ └─ 0, 1, 2, 3, 4, 5 (Part) ├─ Teleport1 (Model) — Glass → TeleportScript └─ Teleport2 (Model) — Glass — финиш наверху ServerScriptService └─ Checkpoints (Script)
Где: ServerScriptService · Script
Зачем: Этапы и появление на чекпоинте.
-- сервис игроков
local Players = game:GetService("Players")
-- папка с чекпоинтами 0, 1, 2…
local checkpoints = workspace:WaitForChild("Checkpoints")
-- игрок зашёл
Players.PlayerAdded:Connect(function(player)
-- таблица по Tab
local leaderstats = Instance.new("Folder")
-- имя строго такое
leaderstats.Name = "leaderstats"
-- в игрока
leaderstats.Parent = player
-- номер этапа
local stage = Instance.new("IntValue")
-- столбец «Stage»
stage.Name = "Stage"
-- в таблицу
stage.Parent = leaderstats
-- персонаж появился (и после каждой смерти)
player.CharacterAdded:Connect(function(character)
-- Humanoid персонажа
local humanoid = character:WaitForChild("Humanoid")
-- ждём, пока персонаж соберётся
character:WaitForChild("HumanoidRootPart")
-- чекпоинт текущего этапа
local point = checkpoints:FindFirstChild(tostring(stage.Value))
-- нашёлся
if point then
-- даём Roblox закончить появление на SpawnLocation
task.wait(0.1)
-- ставим над чекпоинтом
character:PivotTo(point.CFrame + Vector3.new(0, 3, 0))
-- конец проверки
end
-- персонаж чего-то коснулся
humanoid.Touched:Connect(function(hit)
-- это следующий по номеру чекпоинт
if hit.Parent == checkpoints and tonumber(hit.Name) == stage.Value + 1 then
-- этап пройден
stage.Value += 1
-- конец проверки
end
-- конец функции
end)
-- конец функции
end)
-- конец функции
end)Где: в каждом KillBrick и в Lava · Script
Зачем: Убивает при касании.
-- деталь, в которой лежит скрипт
local part = script.Parent
-- когда что-то касается детали
part.Touched:Connect(function(hit)
-- Humanoid есть только у персонажей
local humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
-- коснулся персонаж
if humanoid then
-- здоровье в ноль — игрок погибает
humanoid.Health = 0
-- конец проверки
end
-- конец функции
end)Где: SpeedBrick · Script
Зачем: Скорость 25.
-- деталь со скриптом
local part = script.Parent
-- новая скорость; обычная — 16
local SPEED = 25
-- касание
part.Touched:Connect(function(hit)
-- ищем Humanoid
local humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
-- это персонаж
if humanoid then
-- меняем скорость ходьбы
humanoid.WalkSpeed = SPEED
-- конец проверки
end
-- конец функции
end)Где: NormalBrick · Script
Зачем: Скорость 16.
-- деталь со скриптом
local part = script.Parent
-- обычная скорость Roblox
local SPEED = 16
-- касание
part.Touched:Connect(function(hit)
-- ищем Humanoid
local humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
-- это персонаж
if humanoid then
-- меняем скорость ходьбы
humanoid.WalkSpeed = SPEED
-- конец проверки
end
-- конец функции
end)Где: в каждой Step · Script
Зачем: Исчезающая ступень.
-- ступенька
local part = script.Parent
-- ступень уже исчезает — повторные касания не считаем
local busy = false
-- касание
part.Touched:Connect(function(hit)
-- уже исчезает — выходим
if busy then return end
-- исчезает только от игрока
if not hit.Parent:FindFirstChildOfClass("Humanoid") then return end
-- занято
busy = true
-- 20 шагов
for i = 1, 20 do
-- с каждым шагом прозрачнее
part.Transparency = i / 20
-- всего за 1 секунду
task.wait(0.05)
-- конец цикла
end
-- сквозь ступень можно упасть
part.CanCollide = false
-- 2 секунды её нет
task.wait(2)
-- снова видна
part.Transparency = 0
-- снова твёрдая
part.CanCollide = true
-- готова к следующему игроку
busy = false
-- конец функции
end)Где: MovingPlatform · Script
Зачем: Движущаяся платформа.
-- платформа
local platform = script.Parent
-- сколько studs проезжает
local DISTANCE = 14
-- за сколько секунд
local TIME = 3
-- откуда
local start = platform.Position
-- куда: вперёд по передней грани (Front)
local finish = start + platform.CFrame.LookVector * DISTANCE
-- точка, за которую тянем
local attachment = Instance.new("Attachment")
-- в центре платформы
attachment.Parent = platform
-- сила, которая тянет деталь в точку
local align = Instance.new("AlignPosition")
-- тянем к координате, а не к другой детали
align.Mode = Enum.PositionAlignmentMode.OneAttachment
-- кого тянем
align.Attachment0 = attachment
-- сила без предела — игрок её не остановит
align.MaxForce = math.huge
-- скорость: путь за TIME секунд
align.MaxVelocity = DISTANCE / TIME
-- быстро реагирует
align.Responsiveness = 50
-- пока стоим на месте
align.Position = start
-- в платформу
align.Parent = platform
-- держит платформу ровно
local turn = Instance.new("AlignOrientation")
-- к заданному повороту
turn.Mode = Enum.OrientationAlignmentMode.OneAttachment
-- кого держим
turn.Attachment0 = attachment
-- жёстко, без раскачки
turn.RigidityEnabled = true
-- поворот как сейчас
turn.CFrame = platform.CFrame.Rotation
-- в платформу
turn.Parent = platform
-- теперь её двигает физика — игрок едет вместе с ней
platform.Anchored = false
-- физику платформы считает сервер — без рывков
platform:SetNetworkOwner(nil)
-- бесконечно туда-обратно
while true do
-- едем вперёд
align.Position = finish
-- доехали и стоим секунду
task.wait(TIME + 1)
-- едем обратно
align.Position = start
-- доехали и стоим
task.wait(TIME + 1)
-- конец цикла
endГде: Conveyor · Script
Зачем: Лента.
-- лента (Anchored вкл.)
local part = script.Parent
-- скорость ленты; игрок ходит со скоростью 16
local SPEED = 12
-- закреплённая деталь не едет, но везёт всех, кто на ней
part.AssemblyLinearVelocity = part.CFrame.LookVector * SPEEDГде: Ball (и Pad пружины) · Script
Зачем: Возврат на место раз в 30 секунд.
-- маятник или площадка пружины
local part = script.Parent
-- раз в сколько секунд возвращаем на место
local RESET_TIME = 30
-- место и поворот в начале игры
local start = part.CFrame
-- бесконечно
while true do
-- ждём
task.wait(RESET_TIME)
-- гасим скорость
part.AssemblyLinearVelocity = Vector3.zero
-- гасим вращение
part.AssemblyAngularVelocity = Vector3.zero
-- ставим на старое место — маятник снова раскачивается
part.CFrame = start
-- конец цикла
endГде: Teleport1 → Glass · Script
Зачем: Портал к финишу.
-- стекло портала
local glass = script.Parent
-- куда ведёт: имя второго портала в Workspace
local TARGET = "Teleport2"
-- стекло второго портала
local target = workspace:WaitForChild(TARGET):WaitForChild("Glass")
-- касание
glass.Touched:Connect(function(hit)
-- модель персонажа
local character = hit.Parent
-- это не персонаж — выходим
if not character:FindFirstChildOfClass("Humanoid") then return end
-- когда телепортировался в прошлый раз
local last = character:GetAttribute("Teleported") or 0
-- меньше 2 секунд назад — не бросаем обратно
if os.clock() - last < 2 then return end
-- запоминаем время
character:SetAttribute("Teleported", os.clock())
-- ставим в 5 studs перед вторым порталом
character:PivotTo(target.CFrame + target.CFrame.LookVector * 5)
-- конец функции
end)Запусти Play (или Run) и убедись: