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

Roblox中LocalScript使用HTTP请求的可行方案求助

Roblox获取玩家Marketplace库存的解决方案

问题背景

开发Roblox游戏时,需要通过HTTP请求获取玩家的Catalog/Marketplace库存(非游戏内库存),但LocalScript无法发起HTTP请求。将请求逻辑放入ModuleScript后,由于ModuleScript会继承调用它的脚本的权限限制,问题依然存在。

原ModuleScript代码:

local gearManagement = {}

function gearManagement.GetGears(player)
    local HttpService = game:GetService("HttpService")
    local Table = "https://inventory.roproxy.com/v2/users/"..player.UserId.."/inventory?assetTypes=Gear&limit=100&sortOrder=Asc"
    local GearResponse = HttpService:RequestAsync({
        Url = Table,
        Method = "GET"
    });
    if GearResponse.Success then
        local TableBody = HttpService:JSONDecode(GearResponse.Body)
        for i, v in pairs(TableBody) do
            return v
        end
    end 
end

function gearManagement.CheckForViewableInventory(player)
    local HttpService = game:GetService("HttpService")
    local CanSeeInventory = "https://inventory.roproxy.com/v1/users/"..player.UserId.."/can-view-inventory"
    local Response = HttpService:RequestAsync({
        Url = CanSeeInventory,
        Method = "GET"
    });
end

return gearManagement

原LocalScript代码:

local HttpService = game:GetService("HttpService")
local players = game:GetService("Players")
local player = players.LocalPlayer
local serverStorage = game:GetService("ServerStorage")
-- WHY THE HELL DOES THIS NOT WORK???????????? ITS RIGHT THERE GAME, THE UI FOLDER IS RIGHT THERE, WHY ARENT YOU SEEING IT
-- ^i have found out how, local scripts can't interact w/ server stuff
local gearCardBase = script.Parent.Parent.Parent.gearCard
local gearManagement = require(script.Parent.gearManagement)

local Response = gearManagement.CheckForViewableInventory(player)

if Response.Success then -- If it doesnst work, then idk    
    local Body = HttpService:JSONDecode(Response.Body) -- Decoding the table
    if Body.canView == true then
        -- Continue Code
        local Gears = gearManagement.GetGears(player)
        local gearRowNum = 0
        if Gears ~= nil then -- Avoid errors
            for i, v in pairs(Gears) do
                -- print(v.name, v.assetId)
                local newGearCard = gearCardBase:Clone()
                newGearCard.Parent = script.Parent
                newGearCard.Visible = true
                newGearCard.Interactable = true
                
                local gearRowOffset =  gearRowNum * 4 + 1
                local trueI = i-gearRowOffset
                
                local xPositioningNum = 121 + 21 -- 2nd num is the space between the two cards
                local finalXPositioningNum = xPositioningNum * trueI
                newGearCard.Position.X = newGearCard.Position.X + finalXPositioningNum
                
                local yPositioningNum = 166 + 21 -- 2nd num is the space between the two cards
                local finalYPositioningNum = yPositioningNum * gearRowNum
                newGearCard.Position.Y = newGearCard.Position.Y + finalYPositioningNum
                
                newGearCard.gearImage.Image = "rbxthumb://type=Asset&w=150&h=150&id="..v.assetId
            end
        end
    else
        -- might put a warning here
    end
end

核心解决方案

Roblox仅允许服务器端脚本调用HttpService发起HTTP请求,因此需要通过RemoteFunction实现客户端与服务器的通信:

  1. 服务器端脚本处理HTTP请求逻辑
  2. 客户端LocalScript通过RemoteFunction向服务器发起请求,获取数据后处理UI渲染

修正后的代码

1. 服务器端脚本(放入ServerScriptService)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")

-- 创建RemoteFunction,用于客户端-服务器通信
local InventoryRemote = Instance.new("RemoteFunction")
InventoryRemote.Name = "InventoryRemote"
InventoryRemote.Parent = ReplicatedStorage

-- 处理客户端的库存请求
function InventoryRemote:OnServerInvoke(player)
    -- 检查库存是否可见
    local canSeeUrl = string.format("https://inventory.roproxy.com/v1/users/%d/can-view-inventory", player.UserId)
    local visibilityResponse = HttpService:RequestAsync({
        Url = canSeeUrl,
        Method = "GET"
    })

    if not visibilityResponse.Success then
        return false, "无法检查库存可见性"
    end

    local visibilityData = HttpService:JSONDecode(visibilityResponse.Body)
    if not visibilityData.canView then
        return false, "玩家库存为私有状态"
    end

    -- 获取Gear类型库存
    local gearUrl = string.format("https://inventory.roproxy.com/v2/users/%d/inventory?assetTypes=Gear&limit=100&sortOrder=Asc", player.UserId)
    local gearResponse = HttpService:RequestAsync({
        Url = gearUrl,
        Method = "GET"
    })

    if gearResponse.Success then
        return true, HttpService:JSONDecode(gearResponse.Body)
    else
        return false, "获取Gear库存失败"
    end
end

2. 客户端LocalScript(UI相关位置)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local player = Players.LocalPlayer

local gearCardBase = script.Parent.Parent.Parent.gearCard
local InventoryRemote = ReplicatedStorage:WaitForChild("InventoryRemote")

-- 调用服务器端接口,用pcall捕获网络错误
local success, result = pcall(function()
    return InventoryRemote:InvokeServer()
end)

if success then
    local canView, gearData = result
    if canView then
        local gearRowNum = 0
        for i, gear in ipairs(gearData) do
            -- 克隆并配置Gear卡片
            local newGearCard = gearCardBase:Clone()
            newGearCard.Parent = script.Parent
            newGearCard.Visible = true
            newGearCard.Interactable = true

            -- 计算卡片位置(每行4个)
            local gearIndexInRow = (i - 1) % 4
            local xSpacing = 121 + 21 -- 卡片宽度 + 间距
            local ySpacing = 166 + 21 -- 卡片高度 + 间距
            newGearCard.Position = UDim2.new(
                0, 121 + (xSpacing * gearIndexInRow),
                0, 166 + (ySpacing * gearRowNum)
            )

            -- 设置Gear图标
            newGearCard.gearImage.Image = string.format("rbxthumb://type=Asset&w=150&h=150&id=%d", gear.assetId)

            -- 每4个卡片切换到下一行
            if gearIndexInRow == 3 then
                gearRowNum += 1
            end
        end
    else
        -- 库存不可见时的处理
        warn(result)
    end
else
    -- 请求出错时的处理
    warn("请求失败:", result)
end

关键说明

  • 权限问题解决:所有HTTP请求移至服务器端脚本,避开LocalScript的权限限制
  • 数据安全:Roblox会自动验证RemoteFunction的调用者身份,防止恶意请求
  • 错误处理:用pcall包裹InvokeServer,处理网络波动或服务器错误
  • 排版逻辑优化:修正原代码中的索引计算错误,实现每行4个卡片的规整布局

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 04:17:34