Roblox · Tower Defense · урок 7

Волны на экране, победа и публикация

Игроки видят номер волны; после последней волны — Victory, при разрушенной базе — Game Over. Игра публикуется.

Структура

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

ReplicatedStorage
└─ Values (Folder)
   ├─ Waves (IntValue) — номер волны
   └─ State (StringValue) — пусто / Victory / Game Over
StarterGui
└─ InfoGui (ScreenGui)
   ├─ Wave (TextLabel) — вверху экрана
   ├─ State (TextLabel) — по центру, крупно, Visible выкл.
   └─ InfoLocal (LocalScript)
ServerScriptService
└─ MainScript (Script)

Шаги

  1. Values — в ReplicatedStorage: сервер пишет, все клиенты видят.
  2. Публикация: File → Publish to Roblox; Game Settings → Basic Info (название, описание, иконка), Permissions → Public.
  3. Перед публикацией проверь в Output, что нет красных ошибок.

Скрипты

MainScript

Где: ServerScriptService · Script
Зачем: Пишет номер волны и итог игры в Values.

-- модуль врагов
local mob = require(script.Mob)
-- модуль башен
local tower = require(script.Tower)
-- модуль базы
local base = require(script.Base)
-- карта
local map = workspace.Grass

-- серверное хранилище
local SS = game:GetService("ServerStorage")
-- события сервер → сервер
local bindables = SS:WaitForChild("Bindables")
-- база разрушена
local gameOverEvent = bindables:WaitForChild("GameOverEvent")
-- игра ещё идёт
local gameOver = false
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- номер волны и итог игры — их видят игроки
local values = RS:WaitForChild("Values")
-- сколько всего волн
local maxWaves = 5

-- пришёл сигнал о разрушении базы
gameOverEvent.Event:Connect(function()
    -- игра окончена
    gameOver = true
-- конец обработчика
end)

-- у базы 500 здоровья
base.SetParams(map, 500)

-- волны по очереди
for wave = 1, maxWaves do
    -- сообщаем игрокам номер волны
    values.Waves.Value = wave
    -- обычные: 2, 4, 6…
    mob.Spawn("NormalRig", 2 * wave, map)
    -- быстрые
    mob.Spawn("FastRig", 2 * wave, map)
    -- сильные
    mob.Spawn("StrongRig", 2 * wave, map)
    -- ждём: карта пуста или база разрушена
    repeat task.wait(1) until #workspace.Mobs:GetChildren() == 0 or gameOver
    -- база разрушена
    if gameOver then
        -- поражение
        values.State.Value = "Game Over"
        -- убираем оставшихся врагов
        workspace.Mobs:ClearAllChildren()
        -- волн больше нет
        break
    -- последняя волна отбита
    elseif wave == maxWaves then
        -- победа
        values.State.Value = "Victory"
    -- конец проверки
    end
-- следующая волна
end

InfoLocal

Где: StarterGui → InfoGui · LocalScript
Зачем: Показывает номер волны и итог игры.

-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- Waves и State от сервера
local values = RS:WaitForChild("Values")
-- InfoGui
local gui = script.Parent

-- обновляет номер волны
local function UpdateWave()
    -- «Волна 3»
    gui.Wave.Text = "Волна " .. values.Waves.Value
-- конец функции
end

-- показывает итог игры
local function UpdateState()
    -- Victory или Game Over
    gui.State.Text = values.State.Value
    -- пока игра идёт — надпись скрыта
    gui.State.Visible = values.State.Value ~= ""
-- конец функции
end

-- показываем сразу
UpdateWave()
-- показываем сразу
UpdateState()
-- новая волна
values.Waves.Changed:Connect(UpdateWave)
-- игра закончилась
values.State.Changed:Connect(UpdateState)

Проверка

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