Roblox · Шутер · урок 6
Автомат стреляет очередью, пока зажата кнопка. Снайперка — один мощный выстрел и 2 секунды на затвор.
Синим — что добавляем на этом уроке.
Workspace ├─ Rifle (Tool) — копия Gun — автомат │ └─ GunLocal (LocalScript) — версия с очередью └─ Sniper (Tool) — копия Gun — снайперка ├─ GunLocal (LocalScript) — блок выстрела заменён └─ GunServer (Script) — damage = 60, bulletSpeed = 1000
Где: Workspace → Rifle · LocalScript
Зачем: Очередь, пока кнопка зажата; пауза между выстрелами — всегда.
-- оружие (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 gunGui = gun:WaitForChild("GunGui")
-- надпись «30 / 30»
local ammoText = gunGui.Frame.TextLabel
-- камера — для прицела
local camera = workspace.CurrentCamera
-- пауза между выстрелами очереди
local fireRate = 0.1
-- кнопка стрельбы зажата?
local shooting = false
-- очередь уже идёт?
local looping = false
-- обновляет счётчик
local function UpdateAmmo()
-- «патроны / вместимость»
ammoText.Text = ammo.Value .. " / " .. maxAmmo.Value
-- конец функции
end
-- патроны изменились — обновляем
ammo.Changed:Connect(UpdateAmmo)
-- события каждого кадра
local RunService = game:GetService("RunService")
-- показывать оружие в виде от первого лица
local SHOW_GUN = true
-- сейчас целимся?
local aiming = false
-- режим камеры до прицеливания
local normalMode = nil
-- минимальное приближение до прицеливания
local normalMinZoom = nil
-- подписка «оружие видно»
local showConnection = nil
-- включить или выключить вид от первого лица
local function FirstPerson(on)
-- уже так — ничего не делаем
if aiming == on then return end
-- запоминаем
aiming = on
-- начали целиться
if on then
-- запоминаем режим камеры
normalMode = player.CameraMode
-- и минимальное приближение
normalMinZoom = player.CameraMinZoomDistance
-- камера в голове персонажа
player.CameraMode = Enum.CameraMode.LockFirstPerson
-- оружие должно быть видно
if SHOW_GUN then
-- каждый кадр
showConnection = RunService.RenderStepped:Connect(function()
-- все детали оружия
for _, part in ipairs(gun:GetDescendants()) do
-- Roblox прячет их от первого лица — возвращаем
if part:IsA("BasePart") then part.LocalTransparencyModifier = 0 end
-- конец перебора
end
-- конец обработчика
end)
-- конец проверки
end
-- перестали целиться
else
-- оружие снова прячется как обычно
if showConnection then showConnection:Disconnect() end
-- подписки нет
showConnection = nil
-- режим камеры, который был
player.CameraMode = normalMode or Enum.CameraMode.Classic
-- камера обычная
if player.CameraMode == Enum.CameraMode.Classic then
-- отодвигаем камеру назад — иначе останется в голове
player.CameraMinZoomDistance = 10
-- один кадр
task.wait()
-- возвращаем приближение, как было
player.CameraMinZoomDistance = normalMinZoom or 0.5
-- конец проверки
end
-- конец проверки
end
-- конец функции
end
-- взяли оружие в руки
local function OnEquipped()
-- запоминаем
equipped = true
-- в руках — значит, родитель оружия персонаж
local humanoid = gun.Parent:FindFirstChild("Humanoid")
-- анимация задана
if reloadAnimation.AnimationId ~= "" then
-- готовим анимацию перезарядки
animTrack = humanoid:LoadAnimation(reloadAnimation)
-- конец проверки
end
-- показываем счётчик на экране
gunGui.Parent = player.PlayerGui
-- с актуальным числом
UpdateAmmo()
-- курсор-перекрестье
mouse.Icon = "rbxassetid://6884107931"
-- конец функции
end
-- каждый раз, когда берут в руки
gun.Equipped:Connect(OnEquipped)
-- подобрали с земли: скрипт запустился, когда оружие уже в руках, — Equipped был раньше
if gun.Parent and gun.Parent:FindFirstChildOfClass("Humanoid") then OnEquipped() end
-- убрали оружие
gun.Unequipped:Connect(function()
-- запоминаем
equipped = false
-- прячем счётчик обратно в оружие
gunGui.Parent = gun
-- обычный курсор
mouse.Icon = ""
-- выходим из прицела
camera.FieldOfView = 70
-- и из вида от первого лица
FirstPerson(false)
-- очередь прекращается
shooting = false
-- конец обработчика
end)
-- кнопку стрельбы нажали
gun.Activated:Connect(function()
-- зажата
shooting = true
-- очередь уже идёт — вторую не запускаем
if looping then return end
-- начинаем очередь
looping = true
-- пока кнопка зажата и оружие в руках
while shooting and equipped do
-- не перезаряжаемся
if not reloading then
-- патроны есть
if ammo.Value > 0 then
-- выстрел
shotEvent:FireServer(mouse.Hit.Position)
-- минус патрон
ammo.Value -= 1
-- магазин пуст
else
-- щелчок
emptySound:Play()
-- очередь прекращается
shooting = false
-- конец проверки патронов
end
-- конец проверки перезарядки
end
-- пауза — всегда, иначе цикл повесит игру
task.wait(fireRate)
-- следующий выстрел
end
-- очередь закончилась
looping = false
-- конец обработчика
end)
-- кнопку отпустили
gun.Deactivated:Connect(function()
-- очередь прекращается
shooting = false
-- конец обработчика
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)
-- нажата ПКМ
mouse.Button2Down:Connect(function()
-- приближаем камеру — прицел
if equipped then camera.FieldOfView = 30 end
-- смотрим от первого лица
if equipped then FirstPerson(true) end
-- конец обработчика
end)
-- ПКМ отпущена
mouse.Button2Up:Connect(function()
-- обычный обзор
camera.FieldOfView = 70
-- камера снова за спиной
FirstPerson(false)
-- конец обработчика
end)Где: Workspace → Sniper · LocalScript
Зачем: Заменяет блок gun.Activated: после выстрела 2 секунды нельзя стрелять.
-- добавь к переменным: идёт затвор после выстрела?
local shooting = false
-- клик, пока оружие в руках
gun.Activated:Connect(function()
-- перезарядка или затвор — не стреляем
if reloading or shooting then return end
-- патроны есть
if ammo.Value > 0 then
-- затвор занят
shooting = true
-- выстрел
shotEvent:FireServer(mouse.Hit.Position)
-- минус патрон
ammo.Value -= 1
-- 2 секунды на затвор
task.wait(2)
-- можно стрелять снова
shooting = false
-- магазин пуст
else
-- щелчок
emptySound:Play()
-- конец проверки
end
-- конец обработчика
end)Запусти Play (или Run) и убедись: