Roblox · Королевская битва · урок 5
Игроки ждут раунда в лобби на платформе в небе: вошёл в ворота — попал на площадку готовых, табло считает игроков и секунды, по нулю экран темнеет и всех переносит на остров.
Синим — что добавляем на этом уроке.
Workspace ├─ Lobby (Model) — платформа в небе далеко от острова │ ├─ SpawnLocation (SpawnLocation) — все появляются здесь │ ├─ Gate (Model) — арка ворот │ │ ├─ Gate (Part) — светящаяся рамка, CanCollide выкл. │ │ ├─ GuiPart (Part) — невидимая; Board (BillboardGui) → Frame → Status, Players, Time; UIPadding │ │ └─ GateScript (Script) │ ├─ ReadyZone (Model) — Barrier — стенки площадки; TeleportPart — невидимая середина │ └─ LeaveRoomPart (Part) — невидимая, куда вернуть передумавшего └─ MapSpawn (Part) — невидимая точка на острове (до урока «Десантирование») ReplicatedStorage └─ LeaveEvent, TeleportingEvent (RemoteEvent) StarterGui └─ MainGui (ScreenGui) — ResetOnSpawn выкл. ├─ Teleporting (Frame) — на весь экран, чёрный, BackgroundTransparency 1 │ ├─ TextLabel (TextLabel) — TextTransparency 1 │ └─ TeleportingLocal (LocalScript) └─ LeaveButton (TextButton) — «Выйти» └─ LeaveLocal (LocalScript)
Где: Workspace → Lobby → Gate · Script
Зачем: Готовые, табло, отправка.
-- игроки
local Players = game:GetService("Players")
-- события
local RS = game:GetService("ReplicatedStorage")
-- сигнал начала раунда
local SS = game:GetService("ServerStorage")
-- модель Gate
local gate = script.Parent
-- модель Lobby
local lobby = gate.Parent
-- светящаяся рамка — войти в неё
local gatePart = gate:WaitForChild("Gate")
-- табло над воротами
local board = gate:WaitForChild("GuiPart"):WaitForChild("Board"):WaitForChild("Frame")
-- площадка готовых
local readyPart = lobby:WaitForChild("ReadyZone"):WaitForChild("TeleportPart")
-- куда вернуть, если передумал
local leavePart = lobby:WaitForChild("LeaveRoomPart")
-- кнопка «Выйти»
local leaveEvent = RS:WaitForChild("LeaveEvent")
-- затемнение экрана
local teleportingEvent = RS:WaitForChild("TeleportingEvent")
-- точка на острове (до урока «Десантирование»)
local mapSpawn = workspace:WaitForChild("MapSpawn")
-- мест в раунде
local MAX_PLAYERS = 30
-- для проверки одному; в настоящей игре поставь 2 и больше
local MIN_PLAYERS = 1
-- секунд отсчёта
local WAIT_TIME = 30
-- игрок → true: кто вошёл в ворота
local ready = {}
-- идёт отправка — ворота закрыты
local sending = false
-- сколько готовых
local function Count()
-- счётчик
local n = 0
-- каждый готовый
for player in pairs(ready) do
-- вышел из игры — убираем
if player.Parent then n += 1 else ready[player] = nil end
-- конец перебора
end
-- число
return n
-- конец функции
end
-- обновить табло
local function UpdateBoard(status, seconds)
-- готовые
board.Players.Text = "Игроков: " .. Count() .. "/" .. MAX_PLAYERS
-- состояние
board.Status.Text = status
-- отсчёт
board.Time.Text = seconds and (seconds .. " с") or ""
-- конец функции
end
-- кто-то вошёл в ворота
gatePart.Touched:Connect(function(hit)
-- модель персонажа
local character = hit.Parent
-- игрок (а не NPC или предмет)
local player = Players:GetPlayerFromCharacter(character)
-- Humanoid
local humanoid = character:FindFirstChildOfClass("Humanoid")
-- уже готов, отправка или погиб
if not player or ready[player] or sending or not humanoid or humanoid.Health <= 0 then return end
-- мест нет
if Count() >= MAX_PLAYERS then return end
-- готов
ready[player] = true
-- на площадку готовых
character:PivotTo(readyPart.CFrame + Vector3.new(math.random(-6, 6), 3, math.random(-6, 6)))
-- показать кнопку «Выйти»
leaveEvent:FireClient(player, true)
-- конец функции
end)
-- нажал «Выйти»
leaveEvent.OnServerEvent:Connect(function(player)
-- не в списке или уже отправляем
if not ready[player] or sending then return end
-- не готов
ready[player] = nil
-- обратно в лобби
if player.Character then player.Character:PivotTo(leavePart.CFrame + Vector3.new(0, 3, 0)) end
-- спрятать кнопку
leaveEvent:FireClient(player, false)
-- конец функции
end)
-- игрок зашёл
local function Setup(player)
-- персонаж пропал — не готов
player.CharacterRemoving:Connect(function() ready[player] = nil end)
-- конец функции
end
-- новые игроки
Players.PlayerAdded:Connect(Setup)
-- кто зашёл раньше скрипта
for _, player in ipairs(Players:GetPlayers()) do Setup(player) end
-- бесконечно
while true do
-- отсчёт с начала
local left = WAIT_TIME
-- пока не 0
while left > 0 do
-- мало игроков
if Count() < MIN_PLAYERS then
-- отсчёт заново
left = WAIT_TIME
-- табло
UpdateBoard("ЖДЁМ ИГРОКОВ")
-- хватает
else
-- табло с секундами
UpdateBoard("ГОТОВЬСЯ", left)
-- минус секунда
left -= 1
-- конец проверки
end
-- секунда
task.wait(1)
-- конец отсчёта
end
-- ворота закрыты
sending = true
-- кого отправляем
local list = {}
-- готовые
for player in pairs(ready) do
-- ещё в игре
if player.Parent then
-- в список
table.insert(list, player)
-- кнопка «Выйти» больше не нужна
leaveEvent:FireClient(player, false)
-- экран темнеет
teleportingEvent:FireClient(player)
-- конец проверки
end
-- конец перебора
end
-- список пуст
table.clear(ready)
-- табло
UpdateBoard("ОТПРАВКА")
-- экран успел потемнеть
task.wait(2)
-- каждого
for _, player in ipairs(list) do
-- на остров
if player.Character then player.Character:PivotTo(mapSpawn.CFrame + Vector3.new(math.random(-10, 10), 4, math.random(-10, 10))) end
-- конец перебора
end
-- ворота снова открыты
sending = false
-- конец цикла
endГде: StarterGui → MainGui → Teleporting · LocalScript
Зачем: Затемнение.
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- плавность
local TS = game:GetService("TweenService")
-- Frame «Teleporting» на весь экран
local background = script.Parent
-- надпись
local text = background:WaitForChild("TextLabel")
-- сервер отправляет
local teleportingEvent = RS:WaitForChild("TeleportingEvent")
-- 2 секунды
local info = TweenInfo.new(2)
-- отправка
teleportingEvent.OnClientEvent:Connect(function()
-- экран темнеет
TS:Create(background, info, {BackgroundTransparency = 0}):Play()
-- надпись проявляется
TS:Create(text, info, {TextTransparency = 0}):Play()
-- пока переносят
task.wait(3.5)
-- экран светлеет
TS:Create(background, info, {BackgroundTransparency = 1}):Play()
-- надпись исчезает
TS:Create(text, info, {TextTransparency = 1}):Play()
-- конец функции
end)Где: StarterGui → MainGui → LeaveButton · LocalScript
Зачем: Кнопка «Выйти».
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- кнопка «Выйти»
local button = script.Parent
-- событие
local leaveEvent = RS:WaitForChild("LeaveEvent")
-- сначала скрыта
button.Visible = false
-- сервер: показать или спрятать
leaveEvent.OnClientEvent:Connect(function(show)
-- видна или нет
button.Visible = show
-- конец функции
end)
-- клик
button.MouseButton1Click:Connect(function()
-- просим вернуть в лобби
leaveEvent:FireServer()
-- конец функции
end)Запусти Play (или Run) и убедись: