You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Roblox脚本问题:触发多次时重复发放GamePass道具求解决

解决GamePass道具重复发放问题

针对你遇到的重复发放道具问题,下面是基于背包检测方案的修复脚本,同时修正了原脚本里的语法和逻辑错误:

local MarketplaceService = game:GetService("MarketplaceService")
local ServerStorage = game:GetService("ServerStorage")

local swordPromptPart = game.Workspace.PromptSword
local GAMEPASS_ID = 1273710699 -- 统一GamePass ID,避免不一致
local ITEM_NAME = "Sword" -- 要发放的道具名称

-- 辅助函数:检查玩家是否已拥有目标道具
local function playerHasItem(player, itemName)
    -- 检查背包
    if player.Backpack:FindFirstChild(itemName) then
        return true
    end
    -- 检查StarterGear(确保重生后也有)
    if player.StarterGear:FindFirstChild(itemName) then
        return true
    end
    -- 检查角色身上(如果道具被装备)
    if player.Character and player.Character:FindFirstChild(itemName) then
        return true
    end
    return false
end

-- 购买成功后发放道具
local function onGamepassPurchase(player, purchasePassID, purchaseSuccess)
    if purchaseSuccess and purchasePassID == GAMEPASS_ID then
        -- 先检查是否已有道具,避免重复发放
        if not playerHasItem(player, ITEM_NAME) then
            -- 克隆道具到背包和StarterGear
            ServerStorage:WaitForChild(ITEM_NAME):Clone().Parent = player.Backpack
            ServerStorage:WaitForChild(ITEM_NAME):Clone().Parent = player.StarterGear
            -- 显示冲刺按钮(服务器端通过PlayerGui访问)
            local sprintGui = player.PlayerGui:WaitForChild("SprintGui")
            if sprintGui then
                sprintGui.SprintButton.Visible = true
            end
        end
    end
end

-- 触发购买提示或发放道具
local function promptPurchase(otherPart)
    local humanoid = otherPart.Parent:FindFirstChild("Humanoid")
    if not humanoid then return end
    
    local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
    if not player then return end

    -- 先检查是否已有道具,有则直接返回
    if playerHasItem(player, ITEM_NAME) then
        return
    end

    -- 检查玩家是否拥有GamePass
    local hasPass = false
    local success, message = pcall(function()
        hasPass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, GAMEPASS_ID)
    end)

    if not success then
        warn("检查GamePass失败: " .. message)
        return
    end

    if hasPass then
        print(player.Name .. " 已拥有剑的GamePass,发放道具")
        -- 直接发放道具(因为已拥有但还没拿到)
        if not playerHasItem(player, ITEM_NAME) then
            ServerStorage:WaitForChild(ITEM_NAME):Clone().Parent = player.Backpack
            ServerStorage:WaitForChild(ITEM_NAME):Clone().Parent = player.StarterGear
            local sprintGui = player.PlayerGui:WaitForChild("SprintGui")
            if sprintGui then
                sprintGui.SprintButton.Visible = true
            end
        end
    else
        MarketplaceService:PromptGamePassPurchase(player, GAMEPASS_ID)
    end 
end

-- 连接事件
MarketplaceService.PromptGamePassPurchaseFinished:Connect(onGamepassPurchase)
-- 给Touched事件加防重复触发(用debounce)
local debounce = {}
swordPromptPart.Touched:Connect(function(otherPart)
    local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
    if not player then return end
    -- 冷却1秒,避免短时间内重复触发
    if debounce[player.UserId] then return end
    debounce[player.UserId] = true
    promptPurchase(otherPart)
    task.wait(1)
    debounce[player.UserId] = nil
end)

关键修改说明

  • 道具存在检测:新增playerHasItem函数,同时检查玩家的背包、StarterGear和角色身上的道具,确保不会重复发放。
  • 统一ID管理:将GamePass ID和道具名称设为常量,避免代码中出现不一致的数值。
  • 修复语法错误:修正了原脚本中pcall的语法错误,以及服务器脚本不能使用LocalPlayer的问题。
  • 防重复触发:给Touched事件添加了debounce(冷却机制),避免玩家触碰时短时间内多次触发逻辑。
  • 完善错误处理:给GamePass检查的pcall添加了错误提示,方便排查问题。

如果你更倾向于隐藏触发区域的方案,只需要在发放道具后执行swordPromptPart.Visible = false或者swordPromptPart.CanCollide = false即可,但背包检测方案更灵活,适合需要玩家多次触发但不重复发道具的场景。

内容的提问来源于stack exchange,提问作者R Reveley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 18:42:39