← Все практические скрипты
Игровые системы · Продвинутый · 40 мин

Магазин ускорений через единый контроллер

Купите временное ускорение за монеты, не сбрасывая другие бонусы.

Иллюстрация: Магазин ускорений через единый контроллер
🎯 Что получится

За 10 монет игрок получает ускорение на 20 секунд. Другие бонусы продолжают работать.

1. Подготовьте объект

Где разместить: ServerScriptService: StatsController и SpeedShopServer; Workspace: SpeedShop (Part) с ProximityPrompt.

Структура в Explorer
ServerScriptService
  StatsController (ModuleScript из практики 91)
  SpeedShopServer (Script)
Workspace
  SpeedShop (Part)
    ProximityPrompt
  1. Сначала установите StatsController из практики 91, но не копируйте его второй раз.
  2. Создайте Part SpeedShop в Workspace, добавьте ProximityPrompt, задайте ActionText «Купить ускорение», ObjectText «Магазин», HoldDuration 0.5.
  3. В ServerScriptService создайте Script SpeedShopServer и вставьте код.
  4. Используйте только одну систему leaderstats.Coins. Этот урок НЕ создаёт и НЕ сохраняет валюту.
  5. Дайте тестовому игроку 20 Coins в своей системе монет. Подойдите к магазину и нажмите E.
  6. Проверьте недостаток монет, покупку с бонусом SpeedPad, истечение 20 секунд и двух игроков.
  7. При отсутствии Coins покупка не происходит; сообщения о покупке видны в Output сервера.

2. Вставьте код

Script + ModuleScript из практики 91
-- Script: ServerScriptService/SpeedShopServer
local Players = game:GetService("Players")
local Controller = require(script.Parent:WaitForChild("StatsController"))
local prompt = workspace:WaitForChild("SpeedShop"):WaitForChild("ProximityPrompt")
local PRICE = 10
local DURATION = 20
local busy = {}
-- Не берём повторную плату, пока действует купленный бонус.
local paidUntil = {}
local paidCharacter = {}

prompt.Triggered:Connect(function(player)
    if busy[player] then return end
    busy[player] = true
    local character = player.Character
    local now = os.clock()
    if paidCharacter[player] == character and now < (paidUntil[player] or 0) then
        busy[player] = nil
        return
    end
    local humanoid = character and character:FindFirstChildOfClass("Humanoid")
    local root = character and character:FindFirstChild("HumanoidRootPart")
    local shop = prompt.Parent
    local stats = player:FindFirstChild("leaderstats")
    local coins = stats and stats:FindFirstChild("Coins")
    if not humanoid or humanoid.Health <= 0 or not root
        or not shop:IsA("BasePart") or (root.Position - shop.Position).Magnitude > 15
        or not coins or not coins:IsA("IntValue") or coins.Value < PRICE then
        busy[player] = nil
        return
    end
    if Controller.Apply(player, "ShopSpeed", {speed = 1.5}, DURATION) then
        coins.Value -= PRICE
        paidUntil[player] = now + DURATION
        paidCharacter[player] = character
        print(player.Name .. " купил ускорение за " .. PRICE .. " монет")
    end
    busy[player] = nil
end)
Players.PlayerRemoving:Connect(function(player)
    busy[player] = nil
    paidUntil[player] = nil
    paidCharacter[player] = nil
end)

3. Проверьте в игре

Нажмите Play в Roblox Studio и проверьте действие механики. Если механика не работает, откройте окно Output и проверьте тип скрипта, его расположение и названия объектов.

Ваш прогресс

Когда проверите механику в Roblox Studio, отметьте практику как выполненную. Отметка хранится только в этом браузере, не в личном кабинете.

Если объединяете несколько скриптов

Добавляйте механики по одной и проверяйте окно Output. Не создавайте несколько одинаковых систем монет или интерфейсов; скрипты, меняющие WalkSpeed, прыжок или освещение, могут влиять друг на друга.

⭐ Три шага к собственной игре
1. Повторите и измените

Измените цену на 5 монет.

2. Улучшите

Добавьте второй магазин с другим множителем скорости и названием эффекта.

3. Придумайте своё

Соберите магазин с несколькими улучшениями и протестируйте баланс цен.

4. Проверьте себя

Кто должен проверять количество монет перед покупкой?

🛠 Если не работает

Если покупка не происходит, проверьте leaderstats.Coins (IntValue), ProximityPrompt и названия объектов. В одной игре должен быть только один скрипт создания и сохранения Coins. При недостатке монет сервер ничего не списывает.