Roblox · Tower Defense · урок 2
Враги появляются сами, идут с анимацией, не толкаются и исчезают в конце пути. Главный скрипт запускает 5 волн.
Синим — что добавляем на этом уроке.
ServerStorage └─ Mobs (Folder) — образцы врагов ├─ NormalRig (Model) — PrimaryPart = HumanoidRootPart │ └─ Animation (Animation) — AnimationId ходьбы ├─ FastRig (Model) — WalkSpeed выше └─ StrongRig (Model) — MaxHealth и Health выше Workspace ├─ Grass (Folder) — вся карта │ ├─ Grass (Part) — земля │ ├─ Road (Folder) │ └─ SpawnPart (Part) ├─ Waypoints (Folder) └─ Mobs (Folder) — враги на карте ServerScriptService ├─ PlayerCollisionGroup (Script) └─ MainScript (Script) — волны └─ Mob (ModuleScript) — появление и движение врага
Где: ServerScriptService · Script
Зачем: Записывает все детали персонажа в группу Player.
-- игрок зашёл в игру
game.Players.PlayerAdded:Connect(function(player)
-- появился его персонаж
player.CharacterAdded:Connect(function(character)
-- перебираем все части персонажа
for _, obj in pairs(character:GetDescendants()) do
-- только физические детали
if obj:IsA("BasePart") then
-- группа коллизий Player
obj.CollisionGroup = "Player"
-- конец проверки
end
-- конец перебора
end
-- конец обработчика персонажа
end)
-- конец обработчика игрока
end)Где: ServerScriptService → MainScript · ModuleScript
Зачем: Spawn создаёт врагов на старте, Move ведёт их по точкам и убирает в конце.
-- хранилище с образцами врагов
local SS = game:GetService("ServerStorage")
-- таблица модуля — сюда кладём функции
local mob = {}
-- ведёт врага по маршруту
function mob.Move(enemy, map)
-- Humanoid управляет движением
local humanoid = enemy:WaitForChild("Humanoid")
-- точки маршрута
local waypoints = workspace:FindFirstChild("Waypoints")
-- анимация ходьбы внутри врага
local animation = enemy:FindFirstChild("Animation")
-- загружаем её в Humanoid
local animTrack = humanoid:LoadAnimation(animation)
-- запускаем ходьбу
animTrack:Play()
-- по точкам по порядку
for waypoint = 1, #waypoints:GetChildren() do
-- идём к точке
humanoid:MoveTo(waypoints[waypoint].Position)
-- ждём, пока дойдёт
humanoid.MoveToFinished:Wait()
-- враг погиб по дороге — дальше не идёт
if humanoid.Health <= 0 then return end
-- следующая точка
end
-- дошёл до конца — убираем
enemy:Destroy()
-- конец функции
end
-- создаёт quantity врагов с именем name
function mob.Spawn(name, quantity, map)
-- ищем образец
local mobModel = SS.Mobs:FindFirstChild(name)
-- образец найден
if mobModel then
-- нужное количество раз
for i = 1, quantity do
-- пауза между врагами
task.wait(0.5)
-- копия врага
local mobClone = mobModel:Clone()
-- ставим на старт
mobClone.PrimaryPart.CFrame = map.SpawnPart.CFrame
-- кладём на карту
mobClone.Parent = workspace.Mobs
-- все детали врага
for _, obj in pairs(mobClone:GetDescendants()) do
-- только физические
if obj:IsA("BasePart") then
-- группа коллизий Mob
obj.CollisionGroup = "Mob"
-- конец проверки
end
-- конец перебора
end
-- враг погиб
mobClone.Humanoid.Died:Connect(function()
-- короткая пауза
task.wait(0.5)
-- убираем тело с карты
mobClone:Destroy()
-- конец обработчика смерти
end)
-- движение параллельно — не ждём, пока враг пройдёт путь
coroutine.wrap(mob.Move)(mobClone, map)
-- следующий враг
end
-- конец проверки
end
-- конец функции
end
-- отдаём таблицу тому, кто вызвал require
return mobГде: ServerScriptService · Script
Зачем: 5 волн: в каждой врагов больше; новая волна — когда карта пуста.
-- подключаем модуль врагов
local mob = require(script.Mob)
-- карта
local map = workspace.Grass
-- 5 волн
for wave = 1, 5 do
-- обычные: 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
-- следующая волна
endЗапусти Play (или Run) и убедись: