Roblox · Шутер · урок 4

Магазин и перезарядка

Патроны кончаются — щелчок пустого магазина. R — перезарядка со звуком и анимацией, во время неё стрелять нельзя.

Структура

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

Workspace
└─ Gun (Tool)
   ├─ Handle (Part)
   │  ├─ Shoot (Sound)
   │  ├─ Empty (Sound) — щелчок пустого магазина
   │  └─ Reload (Sound) — перезарядка
   ├─ Ammo (NumberValue) — Value = вместимость
   ├─ MaxAmmo (NumberValue) — вместимость магазина
   ├─ Shot (RemoteEvent)
   ├─ GunLocal (LocalScript)
   │  └─ Animation (Animation) — AnimationId перезарядки
   └─ GunServer (Script)

Шаги

  1. Звуки: «Empty Clip» → Empty, «Reload» → Reload, оба в Handle.
  2. Ammo и MaxAmmo — одинаковые значения, например 30.
  3. Анимация: Avatar → Rig Builder, оружие внутрь рига, Animation Editor; длина ≈ длине звука Reload.
  4. Приоритет Action (выше Idle и Movement, иначе ходьба перебьёт), Publish, id → Animation.AnimationId.

Скрипты

GunLocal

Где: Workspace → Gun · LocalScript
Зачем: Считает патроны, щёлкает пустым магазином, перезаряжает по R.

-- оружие (Tool)
local gun = script.Parent
-- сигнал «выстрел» на сервер
local shotEvent = gun:WaitForChild("Shot")
-- этот игрок
local player = game.Players.LocalPlayer
-- его мышь: mouse.Hit — точка под курсором
local mouse = player:GetMouse()
-- оружие в руках?
local equipped = false
-- нажатия клавиш
local UIS = game:GetService("UserInputService")
-- модель оружия
local handle = gun:WaitForChild("Handle")
-- щелчок пустого магазина
local emptySound = handle:WaitForChild("Empty")
-- звук перезарядки
local reloadSound = handle:WaitForChild("Reload")
-- патроны в магазине сейчас
local ammo = gun:WaitForChild("Ammo")
-- вместимость магазина
local maxAmmo = gun:WaitForChild("MaxAmmo")
-- анимация перезарядки
local reloadAnimation = script:WaitForChild("Animation")
-- загрузим, когда возьмём оружие
local animTrack = nil
-- идёт перезарядка?
local reloading = false

-- взяли оружие в руки
local function OnEquipped()
    -- запоминаем
    equipped = true
    -- в руках — значит, родитель оружия персонаж
    local humanoid = gun.Parent:FindFirstChild("Humanoid")
    -- анимация задана
    if reloadAnimation.AnimationId ~= "" then
        -- готовим анимацию перезарядки
        animTrack = humanoid:LoadAnimation(reloadAnimation)
    -- конец проверки
    end
-- конец функции
end
-- каждый раз, когда берут в руки
gun.Equipped:Connect(OnEquipped)
-- подобрали с земли: скрипт запустился, когда оружие уже в руках, — Equipped был раньше
if gun.Parent and gun.Parent:FindFirstChildOfClass("Humanoid") then OnEquipped() end

-- убрали оружие
gun.Unequipped:Connect(function()
    -- запоминаем
    equipped = false
-- конец обработчика
end)

-- клик, пока оружие в руках
gun.Activated:Connect(function()
    -- во время перезарядки не стреляем
    if reloading then return end
    -- патроны есть
    if ammo.Value > 0 then
        -- выстрел
        shotEvent:FireServer(mouse.Hit.Position)
        -- минус патрон
        ammo.Value -= 1
    -- магазин пуст
    else
        -- щелчок
        emptySound:Play()
    -- конец проверки
    end
-- конец обработчика
end)

-- нажата клавиша
UIS.InputBegan:Connect(function(input, gp)
    -- печатает в чат / оружие не в руках / уже перезаряжаемся
    if gp or not equipped or reloading then return end
    -- R, и магазин не полный
    if input.KeyCode == Enum.KeyCode.R and ammo.Value < maxAmmo.Value then
        -- началась перезарядка
        reloading = true
        -- звук
        reloadSound:Play()
        -- анимация, если задана
        if animTrack then animTrack:Play() end
        -- ждём длину звука (минимум 1 с — даже если звук не загрузился)
        task.wait(math.max(reloadSound.TimeLength, 1))
        -- полный магазин
        ammo.Value = maxAmmo.Value
        -- перезарядка закончилась
        reloading = false
    -- конец проверки
    end
-- конец обработчика
end)

Проверка

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