Roblox · Захват флага · урок 5

Таймер раунда

Игра идёт раундами: 30 секунд в лобби, потом 5 минут на поле, и снова. Время видно вверху экрана.

Структура

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

ReplicatedStorage
├─ Lobby (BoolValue)
└─ TimeLeft (IntValue) — секунды до конца этапа
ServerScriptService
└─ TimerServer (Script)
StarterGui
└─ TimerGui (ScreenGui) — ResetOnSpawn выкл.
   ├─ TimerLabel (TextLabel) — вверху по центру
   └─ TimerLocal (LocalScript)

Шаги

  1. ReplicatedStorage → IntValue «TimeLeft». Сервер пишет туда секунды, все клиенты видят.
  2. ServerScriptService → Script «TimerServer». В методичке лобби и игра проходили один раз — здесь цикл while true.
  3. Перенос — через RespawnLocation и LoadCharacter: игрок возрождается на точке своей команды, а флаг, если он его нёс, сам возвращается домой (FlagServer ловит CharacterRemoving).
  4. Игроки без команды остаются в лобби, пока не выберут.
  5. TimerGui → TextLabel «TimerLabel» вверху по центру и LocalScript «TimerLocal».
  6. %02d — число двумя цифрами с нулём впереди; t // 60 — целые минуты, t % 60 — остаток секунд.

Скрипты

TimerServer

Где: ServerScriptService · Script
Зачем: Лобби и игра по кругу.

-- игроки
local Players = game:GetService("Players")
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- идёт лобби?
local lobby = RS:WaitForChild("Lobby")
-- сколько секунд осталось
local timeLeft = RS:WaitForChild("TimeLeft")
-- секунд в лобби
local LOBBY_TIME = 30
-- секунд игры (5 минут)
local GAME_TIME = 300

-- всех игроков с командой — на точки своей команды
local function SendAll(folder)
    -- каждый игрок
    for _, player in ipairs(Players:GetPlayers()) do
        -- команда выбрана
        if player.Team then
            -- точка команды в этой папке
            player.RespawnLocation = folder:FindFirstChild(player.Team.Name)
            -- возрождаем там (флаг сам вернётся)
            player:LoadCharacter()
        -- конец проверки
        end
    -- конец перебора
    end
-- конец функции
end

-- обратный отсчёт
local function Countdown(seconds)
    -- от seconds до 0
    for t = seconds, 0, -1 do
        -- игроки видят время
        timeLeft.Value = t
        -- секунда
        task.wait(1)
    -- конец цикла
    end
-- конец функции
end

-- раунды по кругу
while true do
    -- лобби
    lobby.Value = true
    -- все в лобби
    SendAll(workspace.LobbySpawn)
    -- ждём
    Countdown(LOBBY_TIME)
    -- игра
    lobby.Value = false
    -- обнуляем счёт
    for _, player in ipairs(Players:GetPlayers()) do
        -- таблица
        local stats = player:FindFirstChild("leaderstats")
        -- с нуля
        if stats then stats.Flags.Value = 0 end
    -- конец перебора
    end
    -- все на поле
    SendAll(workspace.GameSpawn)
    -- играем
    Countdown(GAME_TIME)
-- конец цикла
end

TimerLocal

Где: StarterGui → TimerGui · LocalScript
Зачем: Время на экране.

-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- идёт лобби?
local lobby = RS:WaitForChild("Lobby")
-- секунды
local timeLeft = RS:WaitForChild("TimeLeft")
-- надпись
local label = script.Parent:WaitForChild("TimerLabel")

-- обновить надпись
local function Update()
    -- секунды
    local t = timeLeft.Value
    -- что идёт
    local prefix = lobby.Value and "До начала: " or "До конца: "
    -- минуты и секунды с нулём: 01:05
    label.Text = prefix .. string.format("%02d:%02d", t // 60, t % 60)
-- конец функции
end

-- каждую секунду
timeLeft.Changed:Connect(Update)
-- лобби ↔ игра
lobby.Changed:Connect(Update)
-- сразу при входе
Update()

Проверка

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