Roblox · Дополнительное

Спаунер оружия

Цилиндр-подставка, над ним крутится и покачивается оружие. Подходишь — «Взять» (E) — оружие в инвентаре, цилиндр краснеет на 60 секунд, витрина пропадает; потом всё возвращается. Выдаёт любой Tool: оружие, аптечку, энергетик.

Структура

Синим — что нужно создать.

ServerStorage
└─ Pistol (Tool) — любой готовый Tool, который будем выдавать
Workspace
└─ WeaponSpawner (Model)
   ├─ Pad (Part) — Shape Cylinder, Orientation 0, 0, 90, Anchored
   │  └─ ProximityPrompt (ProximityPrompt) — HoldDuration 0.3, MaxActivationDistance 8
   ├─ Configuration (Configuration)
   │  ├─ Tool (ObjectValue) — Value → ServerStorage.Pistol
   │  ├─ Cooldown (NumberValue) — секунд перезарядки, 60
   │  └─ Height (NumberValue) — высота витрины, 3
   ├─ SpawnerServer (Script)
   └─ Display (Model) — витрину создаёт скрипт сам: копии всех деталей предмета

Шаги

  1. Предмет для выдачи: любой готовый Tool (оружие, аптечка) перетащи в ServerStorage — там его не видно и скрипты внутри не работают, пока его не выдадут.
  2. Workspace → «+» → Model, переименуй в WeaponSpawner.
  3. В WeaponSpawner: «+» → Part, переименуй в Pad. В Properties: Shape — Cylinder, Orientation — 0, 0, 90 (цилиндр встанет вертикально), Size — 1, 4, 4 (первое число — высота), Anchored — вкл.
  4. В Pad: «+» → ProximityPrompt. HoldDuration — 0.3 (сколько держать E), MaxActivationDistance — 8.
  5. Configuration — папка для настроек (как Folder, значок шестерёнки): наведи на WeaponSpawner → «+» → Configuration. Внутри создай по списку: «+» → NumberValue (если в скобках другой тип — его) → переименуй → в Properties впиши Value:
    • Tool (ObjectValue) — в Value выбери предмет из ServerStorage — его и будет выдавать спаунер
    • Cooldown = 60 — секунд, пока спаунер красный и не выдаёт
    • Height = 3 — на сколько studs над цилиндром висит витрина
  6. В WeaponSpawner: «+» → Script, переименуй в SpawnerServer, вставь текст SpawnerServer из «Скриптов».
  7. Как работает: витрина — модель (Model) из копий всех деталей предмета, поэтому оружие из нескольких частей (рукоять, ствол, магазин, прицел) видно целиком. Скрипт каждый кадр двигает модель одной командой PivotTo — детали не разъезжаются. Нажал «Взять» — копия предмета летит в инвентарь (Backpack), витрина убирается, спаунер краснеет и ждёт Cooldown.
  8. У кого такой предмет уже есть, второй не получит — спаунеры не превратятся в склад одинакового оружия.

Скрипты

SpawnerServer

Где: Workspace → WeaponSpawner · Script
Зачем: Крутит витрину, выдаёт предмет по ProximityPrompt и ставит спаунер на перезарядку.

-- модель спаунера
local spawner = script.Parent
-- цилиндр-подставка
local pad = spawner:WaitForChild("Pad")
-- надпись «Взять» — появляется, когда подходишь
local prompt = pad:WaitForChild("ProximityPrompt")
-- настройки
local config = spawner:WaitForChild("Configuration")
-- события каждого кадра
local RunService = game:GetService("RunService")
-- что выдаём: Tool из ServerStorage
local tool = config.Tool.Value
-- в Configuration → Tool ничего не выбрано
if not tool then
    -- подсказка в Output
    warn("Спаунер: выбери Tool в Configuration")
    -- дальше не работаем
    return
-- конец проверки
end

-- исходный цвет цилиндра
local readyColor = pad.Color
-- можно брать?
local ready = true
-- угол поворота витрины
local angle = 0
-- текст на кнопке
prompt.ActionText = "Взять"
-- что берём
prompt.ObjectText = tool.Name

-- витрина — модель: соберём её из копий всех деталей предмета
local display = Instance.new("Model")
-- имя
display.Name = "Display"
-- всё, что внутри предмета
for _, part in pairs(tool:GetDescendants()) do
    -- только детали: Handle, ствол, магазин, прицел…
    if part:IsA("BasePart") then
        -- копия детали вместе с её видом (меш, текстура)
        local copy = part:Clone()
        -- что лежит внутри копии
        for _, child in pairs(copy:GetDescendants()) do
            -- скрипты, звуки и сварки витрине не нужны
            if child:IsA("BaseScript") or child:IsA("Sound") or child:IsA("JointInstance") or child:IsA("WeldConstraint") then
                -- убираем
                child:Destroy()
            -- конец проверки
            end
        -- конец перебора
        end
        -- висит в воздухе
        copy.Anchored = true
        -- сквозь неё можно пройти
        copy.CanCollide = false
        -- не срабатывает на касания
        copy.CanTouch = false
        -- в модель витрины
        copy.Parent = display
    -- конец проверки
    end
-- конец перебора
end
-- центр вращения — рукоять (нет рукояти — центр модели)
display.PrimaryPart = display:FindFirstChild("Handle")
-- показываем
display.Parent = spawner

-- каждый кадр
RunService.Heartbeat:Connect(function(dt)
    -- 90 градусов в секунду
    angle += dt * 90
    -- плавно качается вверх-вниз
    local float = math.sin(os.clock() * 2) * 0.3
    -- над цилиндром на высоте Height
    local position = pad.Position + Vector3.new(0, config.Height.Value + float, 0)
    -- двигаем всю модель сразу: детали не разъезжаются
    display:PivotTo(CFrame.new(position) * CFrame.Angles(0, math.rad(angle), 0))
-- конец обработчика
end)

-- игрок нажал «Взять»
prompt.Triggered:Connect(function(player)
    -- спаунер на перезарядке
    if not ready then return end
    -- инвентарь игрока
    local backpack = player:FindFirstChild("Backpack")
    -- инвентаря нет
    if not backpack then return end
    -- персонаж — предмет может быть в руках
    local character = player.Character
    -- такой предмет уже есть
    if backpack:FindFirstChild(tool.Name) or (character and character:FindFirstChild(tool.Name)) then
        -- второй не даём
        return
    -- конец проверки
    end
    -- спаунер занят
    ready = false
    -- копию предмета — в инвентарь
    tool:Clone().Parent = backpack
    -- цилиндр красный
    pad.Color = Color3.fromRGB(200, 40, 40)
    -- витрина пропала — убираем всю модель целиком
    display.Parent = nil
    -- кнопка «Взять» пропала
    prompt.Enabled = false
    -- ждём Cooldown секунд
    task.wait(config.Cooldown.Value)
    -- исходный цвет
    pad.Color = readyColor
    -- витрина снова видна
    display.Parent = spawner
    -- снова можно брать
    prompt.Enabled = true
    -- готов
    ready = true
-- конец обработчика
end)

Проверка

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

Собрать спаунер одной командой