Roblox · Гонки · урок 4
Таймер сверху экрана считает время гонки. Кто первым проехал последний чекпоинт, тот победил: в конце всем показывается имя победителя и его время. Если время вышло, итог показывается всё равно.
Синим — что добавляем на этом уроке.
ReplicatedStorage ├─ Values (Folder) │ ├─ Minutes (IntValue) — 0 │ ├─ Seconds (IntValue) — 0 │ └─ MaxMinutes (IntValue) — сколько минут длится гонка, например 5 └─ WinEvent (RemoteEvent) ServerScriptService ├─ TimerServer (Script) └─ WinServer (Script) StarterGui ├─ TimerGui (ScreenGui) │ └─ Frame (Frame) — вверху по центру │ └─ TextLabel (TextLabel) │ └─ TimerLocal (LocalScript) └─ WinGui (ScreenGui) └─ Frame (Frame) — по центру экрана ├─ Player (TextLabel) ├─ Time (TextLabel) └─ WinLocal (LocalScript)
Где: ServerScriptService · Script
Зачем: Считает время гонки и останавливается, когда оно вышло.
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- прошло минут
local minutes = RS.Values:WaitForChild("Minutes")
-- прошло секунд
local seconds = RS.Values:WaitForChild("Seconds")
-- сколько минут длится гонка
local maxMinutes = RS.Values:WaitForChild("MaxMinutes")
-- каждую секунду
while task.wait(1) do
-- плюс секунда
seconds.Value += 1
-- набралась минута
if seconds.Value > 59 then
-- секунды с нуля
seconds.Value = 0
-- плюс минута
minutes.Value += 1
-- время гонки вышло — таймер стоп
if minutes.Value >= maxMinutes.Value then break end
-- конец проверки
end
-- конец цикла
endГде: StarterGui → TimerGui → Frame → TextLabel · LocalScript
Зачем: Показывает время на экране.
-- надпись таймера
local text = script.Parent
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- минуты
local minutes = RS.Values:WaitForChild("Minutes")
-- секунды
local seconds = RS.Values:WaitForChild("Seconds")
-- обновить надпись
local function Update()
-- всегда две цифры: 01 : 05
text.Text = string.format("%02d : %02d", minutes.Value, seconds.Value)
-- конец функции
end
-- показываем сразу
Update()
-- минуты поменялись — обновляем
minutes.Changed:Connect(Update)
-- секунды поменялись — обновляем
seconds.Changed:Connect(Update)Где: ServerScriptService · Script
Зачем: Записывает время финиша, находит лучшее и показывает итог всем.
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- минуты таймера
local minutes = RS.Values:WaitForChild("Minutes")
-- секунды таймера
local seconds = RS.Values:WaitForChild("Seconds")
-- длительность гонки
local maxMinutes = RS.Values:WaitForChild("MaxMinutes")
-- событие «гонка окончена»
local winEvent = RS:WaitForChild("WinEvent")
-- последний чекпоинт = финиш
local amountOfCheckpoints = #workspace.Checkpoints:GetChildren()
-- лучшее время в секундах (пока — всё время гонки)
local bestSeconds = maxMinutes.Value * 60
-- лучшее время текстом
local bestTime = "—"
-- кто победил
local bestPlayer = "никто"
-- сколько игроков в гонке
local racers = 0
-- сколько доехали
local finished = 0
-- итог уже показан?
local over = false
-- показать победителя всем
local function ShowResult()
-- уже показали
if over then return end
-- больше не показываем
over = true
-- имя и время — всем игрокам
winEvent:FireAllClients(bestPlayer, bestTime)
-- конец функции
end
-- игрок зашёл
game.Players.PlayerAdded:Connect(function(player)
-- ещё один участник
racers += 1
-- таблица игроков
local leaderstats = Instance.new("Folder")
-- имя, которое понимает Roblox
leaderstats.Name = "leaderstats"
-- в игрока
leaderstats.Parent = player
-- время игрока текстом
local timeValue = Instance.new("StringValue")
-- колонка в таблице
timeValue.Name = "Best Time"
-- ещё не финишировал
timeValue.Value = "—"
-- в таблицу
timeValue.Parent = leaderstats
-- счётчик чекпоинтов (создаёт CheckpointsServer)
local index = player:WaitForChild("Index")
-- игрок прошёл чекпоинт
index.Changed:Connect(function(newValue)
-- ещё не финиш
if newValue ~= amountOfCheckpoints then return end
-- доехал
finished += 1
-- его время в секундах — так удобно сравнивать
local total = minutes.Value * 60 + seconds.Value
-- его время текстом
timeValue.Value = string.format("%02d : %02d", minutes.Value, seconds.Value)
-- быстрее всех
if total <= bestSeconds then
-- новый рекорд
bestSeconds = total
-- лидер
bestPlayer = player.Name
-- время лидера
bestTime = timeValue.Value
-- конец проверки
end
-- доехали все — итог
if finished >= racers then ShowResult() end
-- конец обработчика
end)
-- конец обработчика
end)
-- игрок вышел из игры
game.Players.PlayerRemoving:Connect(function()
-- участников меньше
racers -= 1
-- все оставшиеся уже доехали — итог
if racers > 0 and finished >= racers then ShowResult() end
-- конец обработчика
end)
-- прошла минута
minutes.Changed:Connect(function(newValue)
-- время вышло — итог для всех
if newValue >= maxMinutes.Value then ShowResult() end
-- конец обработчика
end)Где: StarterGui → WinGui → Frame · LocalScript
Зачем: Показывает окно с победителем и временем.
-- окно с итогом
local frame = script.Parent
-- надпись с именем
local playerText = frame:WaitForChild("Player")
-- надпись со временем
local timeText = frame:WaitForChild("Time")
-- событие «гонка окончена»
local winEvent = game.ReplicatedStorage:WaitForChild("WinEvent")
-- до финиша окно скрыто
frame.Visible = false
-- сервер прислал итог
winEvent.OnClientEvent:Connect(function(playerName, bestTime)
-- показываем окно
frame.Visible = true
-- кто победил
playerText.Text = "Победитель: " .. playerName
-- за сколько
timeText.Text = "Время: " .. bestTime
-- конец обработчика
end)Запусти Play (или Run) и убедись: