{}const=>[]async()letfn</>var
LuaПрактика

Tool в Roblox: как выдать оружие игроку и не создать дубликаты

Разбираем Tool, Handle, StarterPack, Backpack и ServerStorage, выдаём оружие серверным скриптом за награду и защищаем инвентарь от дублей.

К

Кодик

Автор

6 мин чтения

Чтобы выдать оружие Tool игроку в Roblox, сервер должен клонировать готовый объект Tool в player.Backpack. Для предмета у всех игроков используйте StarterPack. Для награды или покупки храните шаблон в ServerStorage, проверяйте, нет ли предмета в Backpack и Character, затем создавайте одну копию.

Tool - это контейнер для предмета, который игрок может держать и активировать. Обычно внутри есть BasePart с именем Handle. Когда Tool лежит в Backpack, он отображается в панели инвентаря. При экипировке Roblox переносит его в Character, поэтому проверка только Backpack не защищает от дубликатов. StarterGear влияет на предметы после респавна, а StarterPack выдаёт содержимое всем.

1StarterPack

Автоматически копирует предмет каждому игроку при появлении персонажа.

2Backpack

Текущий инвентарь, из которого Tool экипируется.

3ServerStorage

Закрытое от клиента место для серверных шаблонов наград.

Путь Tool из ServerStorage в Backpack игрока
Путь награды: сервер берёт шаблон Tool из папки Tools в ServerStorage, проверяет Backpack и Character и кладёт игроку ровно одну копию.

Tool Roblox: серверный скрипт выдачи оружия

Создайте Tool TrainingSword с Handle и поместите его в папку Tools внутри ServerStorage. Функция ниже подходит для серверного Script. Она проверяет Backpack и Character, поэтому повторная награда не создаёт вторую иконку, если оружие уже есть у игрока или находится в руках.

local ServerStorage = game:GetService("ServerStorage")
local toolsFolder = ServerStorage:WaitForChild("Tools")

local function hasTool(player, toolName)
    local backpack = player:FindFirstChild("Backpack")
    local character = player.Character

    return (backpack and backpack:FindFirstChild(toolName))
        or (character and character:FindFirstChild(toolName))
end

local function giveTool(player, toolName)
    if hasTool(player, toolName) then
        return false
    end

    local template = toolsFolder:FindFirstChild(toolName)
    if not template or not template:IsA("Tool") then
        warn("Tool template was not found:", toolName)
        return false
    end

    -- Клонируем только проверенный серверный шаблон
    template:Clone().Parent = player:WaitForChild("Backpack")
    return true
end

return giveTool
Ожидаемый результат
  • Первый вызов: Tool появляется в Backpack
  • Повторный вызов: функция возвращает false без дубликата

Фрагмент можно поместить в ModuleScript и вызывать после подтверждённой победы или покупки. Не передавайте с клиента произвольный путь к Tool. Сервер получает короткий itemName, сверяет его с разрешённым каталогом и решает, что клонировать. Если предмет должен оставаться после смерти, добавьте отдельную копию в StarterGear или повторно выдайте его при CharacterAdded согласно правилам игры.

🔥 100 000+ учеников уже с нами

Устал читать теорию?
Пора кодить!

Кодик — приложение, где ты учишься программировать через практику. AI-наставник, интерактивные уроки, реальные проекты.

🤖 AI 24/7
🎓 Сертификаты
💰 Бесплатно
🚀 Начать учиться
Присоединились сегодня

Куда положить Tool

ЭлементЧто означаетЧто делать
StarterPackВсе игроки при респавнеБазовый инструмент
BackpackОдин игрок сейчасМгновенная награда
StarterGearОдин игрок после респавнаПредмет до конца сессии
ServerStorageТолько серверЗащищённые шаблоны наград
WorkspaceМожно подобрать в миреКоллекционный предмет

Handle обычно не должен быть Anchored, иначе экипированный персонаж может вести себя странно. Если Tool не требует физической ручки, настройте RequiresHandle. Проверяйте события Equipped, Unequipped и Activated отдельно. Для оружия урон должен вычислять сервер, а клиент может отвечать за анимацию, прицел и быстрый визуальный отклик.

Проверка Tool перед выкаткой: Handle, Anchored, события экипировки
Что проверить у Tool до публикации: есть ли Handle, снят ли с него Anchored, срабатывают ли Equipped, Unequipped и Activated, считает ли урон сервер.

Практика: выдайте TrainingSword и поймайте дубликат

Соберите в Roblox Studio выдачу одного меча и добейтесь, чтобы второй раз он не выдавался. Успехом считайте такую картину: после первого вызова giveTool в Backpack одна иконка TrainingSword, после второго вызова функция вернула false, а иконка осталась одна. Весь код живёт на сервере, клиент в этой сборке ничего не клонирует.

  1. Tool TrainingSword в ServerStorage. Создайте Tool, назовите его TrainingSword, вложите внутрь Part с именем Handle и снимите с ручки Anchored. Перетащите Tool в папку Tools внутри ServerStorage: в Explorer он должен исчезнуть из Workspace и перестать быть виден в игре.
  2. ModuleScript с giveTool. Создайте ModuleScript в ServerScriptService, перенесите туда hasTool и giveTool и верните giveTool из модуля. После сохранения в Output не должно быть красных строк.
  3. Вызов на PlayerAdded. В серверном Script подключите модуль через require и вызовите giveTool(player, 'TrainingSword') в обработчике Players.PlayerAdded. Нажмите Play: иконка TrainingSword появится в панели инвентаря снизу экрана.
  4. Повторный вызов giveTool. Вызовите giveTool для того же игрока второй раз и оберните вызов в print. В Output появится false, а количество иконок в Backpack не изменится.
  5. Проверка через Character. Возьмите меч в руки клавишей 1 и вызовите giveTool в третий раз. Tool в этот момент лежит в Character, но функция снова вернёт false, потому что hasTool смотрит оба места сразу.

Сломайте выдачу намеренно: передайте имя, которого нет в папке Tools, например giveTool(player, 'IceSword'). В Output появится предупреждение «Tool template was not found: IceSword», функция вернёт false и ничего не склонирует, то есть отказ читается по логу, а не по пустому инвентарю. Отдельно верните Handle в Anchored и посмотрите, как экипированный персонаж начинает застревать на месте: так становится понятно, зачем ручку не закрепляют.

Критерий готовности. Вы можете объяснить, почему клон делает серверный Script, а не LocalScript, и почему hasTool проверяет и Backpack, и Character. Подтверждение простое: одна иконка TrainingSword после трёх вызовов подряд и два false в Output. Дополнительно назовите, что случится с этим мечом после смерти персонажа.

Замените прямой вызов серверным каталогом: таблица разрешённых имён на сервере, а с клиента приходит только короткий itemName. Дальше решите судьбу предмета после респавна: либо копия в StarterGear, либо повторная выдача на CharacterAdded. Урон повесьте на Activated и считайте его на сервере, клиенту оставьте анимацию замаха и звук.

Частые ошибки и почему они появляются

Частая ошибка появляется, когда оружие клонирует LocalScript. Такой предмет может быть виден только одному клиенту, а сервер не подтвердит его урон. Вторая ошибка: проверять дубликат только в Backpack, хотя экипированный Tool временно находится в Character. Третья: использовать StarterPack для редкой награды и случайно выдать её всем.

Anchored Handle

Закреплённая ручка может удерживать персонажа. Для обычного экипируемого предмета снимите Anchored.

Шаблон в ReplicatedStorage без причины

Клиент видит этот объект. Для закрытых серверных наград удобнее ServerStorage.

Доверять toolName без списка

Сверяйте идентификатор с серверным каталогом и разрешениями игрока.

Самопроверка

Почему Tool, выданный из LocalScript, видит только один игрок?

Tool, склонированный в LocalScript, существует только на клиенте этого игрока, поэтому сервер о предмете не знает и не подтвердит его урон. Клонируйте шаблон серверным Script, а клиенту оставьте анимацию, прицел и интерфейс.

Где находится Tool, когда игрок держит его в руках?

Экипированный Tool лежит в модели персонажа, то есть в player.Character, а не в Backpack. Поэтому проверка дубликата по одному Backpack пропускает предмет, который сейчас в руках, и выдаёт вторую копию.

Как выдать оружие сразу всем игрокам?

Положите Tool в StarterPack, и Roblox сам скопирует его каждому игроку при появлении персонажа. Для редкой награды StarterPack не подходит: предмет молча получат все, включая тех, кто ничего не выигрывал.

Почему Tool появляется в инвентаре дважды?

Вторая иконка Tool появляется, когда скрипт клонирует шаблон, не проверив, что предмет уже есть у игрока. Перед вызовом Clone ищите объект по имени через FindFirstChild и в Backpack, и в Character.

Зачем хранить шаблон Tool в ServerStorage, а не в ReplicatedStorage?

ServerStorage закрыт от клиента, поэтому шаблон награды не попадает в клиентскую иерархию и его нельзя изучить или подменить с клиента. ReplicatedStorage реплицируется всем подключённым игрокам, и для закрытых наград это лишняя открытость.

Обязателен ли Handle внутри Tool?

Handle нужен Tool по умолчанию: это BasePart с именем Handle, за который персонаж держит предмет. Если предмет не должен держаться в руке, отключите у Tool свойство RequiresHandle, иначе экипировка будет вести себя непредсказуемо.

Что делать дальше

Начните с Tool без урона: проверьте Handle, инвентарь, экипировку и респавн. Затем добавьте серверное правило награды и только потом боевую механику. Функции и таблицы для каталога удобно закрепить на курсе Lua. Связь кнопки с сервером разбирается в статье про RemoteEvent, а безопасный выбор внешних заготовок в материале про бесплатные модели Roblox.

🎯Хватит откладывать

Понравилась статья?
Пора применять на практике!

В Кодик ты не просто читаешь — ты сразу пишешь код. Теория + практика = реальный скилл.

Мгновенная практика
🧠AI объяснит код
🏆Сертификат

Без регистрации • Без карты