Roblox GuidebookБаза знаний
Русский ⌄

Разработка / ROBLOX

Контрольные точки в Roblox Studio: отдельный учебный obby

Создайте две контрольные точки, назначайте место возрождения отдельно каждому игроку и проверяйте смерть, повторное касание, порядок и выход из сеанса.

Прогресс личный и идёт по порядкуОткрыть изображение крупнее ↗
Оригинальная учебная схема, не карта игры — Повтор и ранняя точка не изменяют достигнутый индекс
Обновлено:

Что именно мы строим #

Сделаем маленькую тренировочную дорожку: Start, Checkpoint1 и Checkpoint2. Игрок проходит их по порядку. После подтверждённого касания следующей точки смерть должна возвращать персонажа туда. Возвращение на раннюю площадку не уменьшает прогресс. Второй игрок имеет собственный маршрут и собственное место возрождения. Это понятный контракт, по которому можно сравнивать ожидаемый и фактический результат.

Это новый учебный прототип, а не реализация Stone Trail или другой игры автора сайта. Скрипт ниже написан для этого урока; его поведение разобрано логически, но здесь не выполнен запуск в движке Roblox. Прогресс живёт только в памяти текущего сервера. Мы не создаём сохранение между посещениями, выдачу наград или защиту от всех способов обхода маршрута. Сначала проверьте узкую механику, затем расширяйте её.

1. Подготовьте отдельную сцену и точные имена #

Сохраните новый небольшой проект, чтобы не вмешиваться в рабочую игру. В Workspace нужен один SpawnLocation с именем Start и Folder с именем Checkpoints. Внутри папки создайте два SpawnLocation: Checkpoint1 и Checkpoint2. В ServerScriptService добавьте обычный Script с именем CheckpointServer. Итоговые пути: Workspace.Start, Workspace.Checkpoints.Checkpoint1, Workspace.Checkpoints.Checkpoint2 и ServerScriptService.CheckpointServer. Имена чувствительны к написанию; пробел в Checkpoint 1 изменит путь.

Площадки дорожки могут быть обычными закреплёнными Part. Контрольные точки должны быть именно SpawnLocation, а не похожими по цвету Part. В новой сцене уберите лишние точки появления, которые не относятся к упражнению. Не вставляйте набор неизвестных скриптов вместе с моделью: для этого прототипа достаточно собственных платформ и одного серверного файла. До добавления кода убедитесь, что три точки видны и не лежат друг на друге.

2. Настройте площадки для касания и появления #

Разместите Start, затем Checkpoint1, затем Checkpoint2 вдоль короткой безопасной дорожки. Между ними должно хватать места, чтобы отдельно коснуться каждой. Оставьте свободное пространство над SpawnLocation: персонаж не должен появляться внутри стены, под низким потолком или на краю провала. Цвет и подпись помогают различать точки, но сами по себе не назначают прогресс. Для первого прохода сложные ловушки не нужны.

Таблица ниже задаёт конфигурацию этого упражнения. Скрипт повторяет необходимые значения при старте. Все точки разрешают появление без команд; изменение команды при касании выключено. CanTouch позволяет получать событие касания, а Anchored удерживает площадку на месте. Если позже вы вводите команды или collision groups, это уже другая конфигурация: повторно проверьте доступность точки и физические контакты. Пока оставьте стандартную автоматическую загрузку персонажей включённой.

СвойствоЗначениеЗачем в упражнении
ClassSpawnLocationТочки появления и возрождения
AnchoredtrueПлощадки не падают
CanCollidetrueНа платформе можно стоять
CanTouchtrueФизическое касание обнаруживается
EnabledtrueТочка разрешает появление
NeutraltrueНет ограничения по команде
AllowTeamChangeOnTouchfalseКасание не меняет команду

3. Поместите один серверный скрипт #

Откройте CheckpointServer в ServerScriptService и замените его содержимое кодом ниже. Скопируйте весь пример, а не только обработчик Touched. Таблица checkpoints содержит фиксированный порядок двух объектов; случайный порядок GetChildren здесь не используется. configure проверяет класс объектов и выставляет свойства. Если имя отсутствует, WaitForChild ожидает его; если объект имеет неправильный класс, assert сообщит об ошибке. Исправьте сцену до проверки маршрута.

Скрипт нужен на сервере: он выбирает Player.RespawnLocation и хранит progress отдельно по Player. LocalScript в StarterPlayerScripts не является заменой этого примера. Не добавляйте одновременно второй скрипт, который также назначает RespawnLocation. Начинайте свежий тест после настройки сцены. Если вставить код во время уже идущего теста, назначение места будущего появления не переносит живого персонажа немедленно к Start. Здесь не используется команда телепортации.

local Players = game:GetService("Players")
local start = workspace:WaitForChild("Start")
local folder = workspace:WaitForChild("Checkpoints")
local checkpoints = {
    folder:WaitForChild("Checkpoint1"),
    folder:WaitForChild("Checkpoint2"),
}
local progress = {}

local function configure(spawn)
    assert(spawn:IsA("SpawnLocation"), "Expected SpawnLocation")
    spawn.Anchored = true
    spawn.CanCollide = true
    spawn.CanTouch = true
    spawn.Enabled = true
    spawn.Neutral = true
    spawn.AllowTeamChangeOnTouch = false
end

configure(start)
for _, checkpoint in ipairs(checkpoints) do
    configure(checkpoint)
end

local function initialize(player)
    if progress[player] ~= nil then return end
    progress[player] = 0
    player.RespawnLocation = start
end

Players.PlayerAdded:Connect(initialize)
Players.PlayerRemoving:Connect(function(player)
    progress[player] = nil
end)
for _, player in ipairs(Players:GetPlayers()) do
    initialize(player)
end

for index, checkpoint in ipairs(checkpoints) do
    checkpoint.Touched:Connect(function(hit)
        local character = hit:FindFirstAncestorOfClass("Model")
        if not character then return end
        local player = Players:GetPlayerFromCharacter(character)
        if not player or player.Character ~= character then return end
        local humanoid = character:FindFirstChildOfClass("Humanoid")
        if not humanoid or humanoid.Health <= 0 then return end
        local current = progress[player]
        if current == nil or index ~= current + 1 then return end
        player.RespawnLocation = checkpoint
        progress[player] = index
    end)
end

4. Определите игрока, а не просто коснувшийся объект #

Touched передаёт другую деталь. Это может быть часть персонажа, падающий куб или предмет. Обработчик ищет ближайшую модель, затем спрашивает GetPlayerFromCharacter, соответствует ли она игроку. Дополнительно сравнивается player.Character, находится Humanoid и проверяется положительное Health. Без этих условий обычный предмет или уже умерший персонаж мог бы ошибочно менять состояние. Неподходящее касание заканчивается return до назначения места возрождения.

Пример рассчитан на обычный персонаж с Humanoid в его модели. Если вы строите нестандартный вложенный rig, отдельно адаптируйте поиск модели; не удаляйте проверку игрока только ради исчезновения ошибки. Мы не называем серверное касание доказательством честного прохождения: движение персонажа и физика требуют отдельного анализа безопасности. Для этого урока проверяем корректность персональных контрольных точек в обычном учебном маршруте.

5. Сохраните порядок и устойчивость к повторам #

Новый игрок получает progress 0. Принимается только индекс current + 1: сначала 1, затем 2. После принятия первой точки повторные касания её ногой или другой частью тела уже не равны следующему индексу. После второй точки первая также отклоняется. Таким образом, правило не позволяет ни откатиться, ни пропустить первую площадку. Это выбранное условие упражнения; свободный маршрут потребовал бы другого контракта.

Здесь нет общего debounce, который блокировал бы всех игроков после одного контакта. Ключ таблицы — конкретный Player, а проверка и две записи не содержат task.wait или другого ожидания. Два игрока могут независимо подтверждать точки. Это анализ короткого обработчика, а не обещание безопасности будущего асинхронного кода. Если добавите награду, запрос данных или задержку, заново разберите повторные вызовы и момент изменения состояния.

6. Разделите смерть, новый запуск и повторный вход #

При принятом касании меняется RespawnLocation данного Player. Живой персонаж остаётся там, где стоял; результат проверяется при следующем обычном возрождении. При смерти новая модель персонажа не равна прежней, однако Player остаётся в сеансе, поэтому его запись progress сохраняется. Не обнуляйте progress в CharacterAdded: тогда каждая смерть стирала бы достигнутую точку.

При выходе PlayerRemoving удаляет запись. Повторный вход создаёт новое состояние 0 и назначает Start. Остановка Studio-теста и новый запуск также создают свежую сессию. Отдельной кнопки полного сброса внутри игры в примере нет. Если её добавите позже, договоритесь, что она сбрасывает и индекс, и RespawnLocation; одного изменения надписи недостаточно. Сохранить проект означает сохранить сцену и код, а не память таблицы игрока.

Разные действия — разный срок памятиОткрыть изображение крупнее ↗
Оригинальная учебная схема, не карта игры — Состояние в памяти; постоянного сохранения нет

7. Выполните одиночную проверку по шагам #

В выпадающем списке тестирования Studio выберите Test и начните тест. Этот режим вставляет персонажа; Run запускает симуляцию без аватара и не подходит для первой проверки ходьбой. Начните новую сессию и проверьте появление у Start. Дойдите обычным движением до Checkpoint1, остановитесь на ней, затем организуйте смерть на отдельном безопасно спроектированном участке падения прототипа. Дождитесь обычного возрождения и запишите его место.

Повторите для Checkpoint2. Потом физически вернитесь к первой точке и снова проверьте смерть: ожидается сохранение второй. Не смешивайте этот опыт с Stop и новым Test, потому что новый тест намеренно сбрасывает память. Фактический результат записывайте отдельно от ожидания. Если персонаж не умирает в выбранном месте, это ещё не отрицательный тест RespawnLocation: сначала подтвердите, что действительно произошла смерть и новое появление.

8. Проверьте предметы, пропуск и повторный контакт #

В отдельной попытке дотроньтесь до Checkpoint2 раньше Checkpoint1: условие порядка должно оставить Start. Затем пройдите обе точки нормально. Для предмета создайте обычный незакреплённый куб и дайте ему физически упасть на контрольную площадку. Он не соответствует Player, поэтому не должен менять чей-либо прогресс. Сравнивайте результат через состояние сервера или последующее возрождение нужного игрока, а не через цвет площадки.

Touched связан с физическим движением. Простое изменение CFrame так, чтобы две закреплённые детали перекрылись, не является тем же тестом события. Если контакта нет, проверьте CanTouch у обеих деталей и правила collision groups. Не публикуйте придуманный результат «куб отклонён», пока не выполнили опыт. Таблица проверок далее показывает ожидаемые исходы, а не отчёт о выполненном запуске этого кода.

9. Проверьте двух игроков независимо #

Выберите Server & Clients и два клиента, затем нажмите Play или F7. Игрок A достигает первой точки, игрок B остаётся на Start. После смерти A должен появиться у Checkpoint1, B — у Start. Затем B проходит первую, а A вторую. Сравните оба результата. Проведите также близкие по времени касания первой точки двумя персонажами: общий блокировщик не должен оставлять одного без персонального прогресса.

Не принимайте за доказательство только то, что обе камеры показывают одну окрашенную площадку. Цвет объекта Workspace общий, а RespawnLocation относится к игроку. Следите, какой клиент выполнил действие и какой персонаж возродился. Когда закончите, используйте End Session для завершения всего многоклиентского сеанса. Два локальных клиента проверяют несколько конкретных случаев; они не доказывают производительность большого сервера или правильность нестандартных аватаров.

10. Ищите причину по одному нарушенному условию #

Если точка не работает, двигайтесь от структуры к состоянию: точный путь, класс SpawnLocation, работа обычного серверного Script, CanTouch, живой Player, ожидаемый индекс и допустимость появления. Ошибка имени и отклонённый второй индекс имеют разные причины. Для ошибок выполнения используйте отдельный гайд по Output; этот урок не заменяет общий разбор консоли. В таблице нет отметок «прошло» — заполните их своим наблюдением.

Особенно проверьте, не отключён ли Enabled и не изменено ли Neutral после старта. Точка должна оставаться в Workspace и подходить игроку; поздний чужой скрипт может менять свойства или RespawnLocation. Если получен результат другой площадки, укажите последовательность действий и фактическое место, а не только «сломано». Одно исправление проверяйте в новой понятной попытке. Не добавляйте бесконечные задержки, чтобы скрыть ошибку порядка.

СлучайОжидаемое состояниеЧто проверить
Новый Test / вход0; StartПервое реальное появление
Checkpoint1, затем смерть1; Checkpoint1Дождаться нового персонажа
Checkpoint1 повторноБез измененияКонтакты разных частей тела
Checkpoint2 после первой2; Checkpoint2Смерть возвращает на вторую
Первая после второй2; Checkpoint2Отката нет
Вторая до первой0; StartПропуск отвергнут
Куб или неигровая модельБез измененияНет соответствующего Player
Мёртвый/старый персонажБез измененияHealth и текущий Character
A прошёл, B не прошёлA и B имеют разные целиПроверить обоих после смерти
Выход / Stop и новый тестНовое состояние 0Постоянного сохранения нет

11. Сохраните результат и выберите одно расширение #

Завершите тест и сохраните рабочий прототип под понятным именем. В заметке укажите структуру, версию скрипта, включённую автоматическую загрузку, выполненные одиночные и двухклиентские случаи, ожидаемое и фактическое место появления. Проверка логики в этой статье не означает, что ваш проект уже прошёл Studio-тест. Не переносите механику в рабочую игру, пока не сравнили все важные случаи на своей сцене.

Следующим небольшим расширением может быть персональное сообщение о подтверждении точки или явная кнопка сброса. Постоянное сохранение — отдельная задача с загрузкой, ошибками записи, версиями данных и правилами сброса; здесь DataStore не используется. Не обещайте игрокам «прогресс навсегда». Сначала сохраните ясное различие: смерть возвращает к достигнутой точке в текущем посещении, выход завершает это учебное состояние.

Первоисточники

Roblox Creator Hub
Roblox Creator Hub — Player.RespawnLocation
Roblox Creator Hub — BasePart.Touched and CanTouch
Roblox Creator Hub — Studio testing modes
Roblox Creator Hub — Players lifecycle
Roblox Creator Hub — ServerScriptService