Roblox · Хоррор · урок 5

Монстры

Монстр появляется за спиной и гонится за игроком. Спасение — добежать до света.

Структура

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

ServerStorage
└─ Monster (Model) — Humanoid, HumanoidRootPart, части тела
   └─ MonsterAnim (Script)
Workspace
├─ MonsterSpawn (Part) — невидимая точка позади игрока
├─ MonsterTrigger (Part)
│  └─ MonsterTrigger (Script)
└─ SafeZone (Part) — светлое место
   ├─ PointLight (PointLight)
   └─ LightTrigger (Script)

Шаги

  1. Проще всего: Avatar → Rig Builder → R15 → перекрась части в чёрный, увеличь. В методичке — свой монстр из деталей и плагин RigEdit Lite: так тоже можно, главное — внутри Humanoid и HumanoidRootPart.
  2. Назови модель «Monster», у Humanoid WalkSpeed = 20 (бег игрока — 25, шаг — 16). Скорость монстра решает, насколько страшно.
  3. Внутрь — Script «MonsterAnim»: анимация ходьбы. Для R6-монстра поменяй WALK_ID на 180426354.
  4. Монстра — в ServerStorage. На карте только точка «MonsterSpawn» (невидимая) — позади места, где сработает триггер.
  5. Триггер «MonsterTrigger» со скриптом: монстр появляется и бежит к игроку, ближе 5 studs — поймал.
  6. «SafeZone» — светлая зона с яркой PointLight и скриптом «LightTrigger»: монстр исчезает.
  7. Погоня заканчивается сама: если игрок погиб или монстра убрал свет. Потом триггер можно пройти заново.

Скрипты

MonsterAnim

Где: ServerStorage → Monster · Script
Зачем: Анимация ходьбы монстра.

-- модель монстра
local monster = script.Parent
-- Humanoid
local humanoid = monster:WaitForChild("Humanoid")
-- Animator (создаём, если нет)
local animator = humanoid:FindFirstChildOfClass("Animator") or Instance.new("Animator", humanoid)
-- стандартная ходьба R15; для R6 — 180426354
local WALK_ID = "rbxassetid://507777826"

-- анимация
local walk = Instance.new("Animation")
-- какая
walk.AnimationId = WALK_ID
-- загружаем
local track = animator:LoadAnimation(walk)
-- по кругу
track.Looped = true

-- скорость монстра изменилась
humanoid.Running:Connect(function(speed)
    -- пошёл
    if speed > 0.5 and not track.IsPlaying then
        -- шагаем
        track:Play()
    -- остановился
    elseif speed <= 0.5 and track.IsPlaying then
        -- стоим
        track:Stop()
    -- конец проверки
    end
-- конец функции
end)

MonsterTrigger

Где: Workspace → MonsterTrigger · Script
Зачем: Выпускает монстра и ведёт погоню.

-- образец монстра
local SS = game:GetService("ServerStorage")
-- игроки
local Players = game:GetService("Players")
-- зона
local trigger = script.Parent
-- где появляется монстр
local spawnPoint = workspace:WaitForChild("MonsterSpawn")
-- ближе — поймал
local KILL_DISTANCE = 5
-- монстр уже гонится
local active = false

-- погоня за игроком
local function Chase(monster, player)
    -- Humanoid монстра
    local mHumanoid = monster:WaitForChild("Humanoid")
    -- центр монстра
    local mRoot = monster:WaitForChild("HumanoidRootPart")
    -- движение считает сервер — без рывков
    mRoot:SetNetworkOwner(nil)
    -- пока монстр в игре
    while monster.Parent and mHumanoid.Health > 0 do
        -- персонаж цели
        local character = player.Character
        -- её Humanoid
        local humanoid = character and character:FindFirstChildOfClass("Humanoid")
        -- её центр
        local root = character and character:FindFirstChild("HumanoidRootPart")
        -- цель погибла или ушла — конец погони
        if not humanoid or not root or humanoid.Health <= 0 then break end
        -- бежим к игроку
        mHumanoid:MoveTo(root.Position)
        -- догнал
        if (root.Position - mRoot.Position).Magnitude <= KILL_DISTANCE then
            -- поймал
            humanoid.Health = 0
            -- конец погони
            break
        -- конец проверки
        end
        -- 10 раз в секунду
        task.wait(0.1)
    -- конец цикла
    end
    -- монстр ещё секунду-две стоит
    task.wait(2)
    -- и исчезает
    monster:Destroy()
-- конец функции
end

-- касание зоны
trigger.Touched:Connect(function(hit)
    -- монстр уже бежит
    if active then return end
    -- кто коснулся
    local player = Players:GetPlayerFromCharacter(hit.Parent)
    -- образец
    local sample = SS:FindFirstChild("Monster")
    -- не игрок или монстра нет
    if not player or not sample then return end
    -- занято
    active = true
    -- копия
    local monster = sample:Clone()
    -- на точку появления
    monster:PivotTo(spawnPoint.CFrame)
    -- в игру
    monster.Parent = workspace
    -- гонимся (ждём, пока закончится)
    Chase(monster, player)
    -- можно снова
    active = false
-- конец функции
end)

LightTrigger

Где: Workspace → SafeZone · Script
Зачем: Свет прогоняет монстра.

-- игроки
local Players = game:GetService("Players")
-- светлая зона
local trigger = script.Parent

-- касание
trigger.Touched:Connect(function(hit)
    -- только игрок
    if not Players:GetPlayerFromCharacter(hit.Parent) then return end
    -- монстр в игре?
    local monster = workspace:FindFirstChild("Monster")
    -- свет его прогоняет — погоня закончится
    if monster then monster:Destroy() end
-- конец функции
end)

Проверка

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