【问题标题】:Roblox- how to store large arrays in roblox datastoresRoblox - 如何在 roblox 数据存储中存储大型数组
【发布时间】:2019-02-28 08:34:30
【问题描述】:

我正在尝试制作一款游戏,玩家可以在其中创建自己的建筑物,然后将其保存以供其他玩家查看和玩。但是,roblox 不允许我存储整个创建所需的所有数据(每个积木都有几个属性) 我得到的只是这个错误代码: 104: 无法在 DataStore 中存储数组

任何帮助将不胜感激!

【问题讨论】:

  • 如果 Roblox 有您用来制作游戏内对象的编程语言,您应该将相关部分显示为 minimal reproducible example。这个想法是你告诉我们你想做什么,展示你尝试了什么,并描述你得到了什么结果。见How to Ask

标签: roblox


【解决方案1】:

我不确定这是否是最好的方法,但这是我的尝试。下面是一个表格的例子,你可以使用表格来存储几个值。我认为你可以使用HttpService的JSONEncode函数将表格转换为字符串(希望可以更有效地保存)

JSONEncode(将brick的数据变成一个字符串,可以保存到DataStore中

local HttpService = game:GetService("HttpService")

-- this is an example of what we'll convert into a json string
local exampleBrick = {
    ["Size"] = Vector3.new(3,3,3),
    ["Position"] = Vector3.new(0,1.5,0),
    ["BrickColor"] = BrickColor.new("White")
    ["Material"] = "Concrete"
}

local brickJSON = HttpService:JSONEncode(exampleBrick)
print(brickJSON)

-- when printed, you'll get something like
-- { "Size": Vector3.new(3,3,3), "Position": Vector3.new(0,1.5,0), "BrickColor": BrickColor.new("White"), "Material": "Concrete"}
-- if you want to refer to this string in a script, surround it with two square brackets ([[) e.g. [[{"Size": Vector3.new(3,3,3)... }]]

JSONDecode(读取字符串并将其转换回砖块)

local HttpService = game:GetService("HttpService")
local brickJSON = [[ {"Size": Vector3.new(3,3,3), "Position": Vector3.new(0,1.5,0), "BrickColor": BrickColor.new("White"), "Material": "Concrete"} ]]

function createBrick(tab)
    local brick = Instance.new("Part")
    brick.Parent = <insert parent here>
    brick.Size = tab[1]
    brick.Position= tab[2]
    brick.BrickColor= tab[3]
    brick.Material= tab[4]
end

local brickData = HttpService:JSONDecode(brickJSON)
createBrick(brickData) --this line actually spawns the brick

如果您想解决任何可能的数据存储错误,也可以将函数包装在 pcall 中。

将整个模型编码为字符串

假设你的玩家的“建筑”是一个模型,你可以使用上面的encode脚本将模型内的所有部分转换成json字符串保存。

local HttpService = game:GetService("HttpService")
local StuffWeWantToSave = {}

function getPartData(part)
    return( {part.Size,part.Position,part.BrickColor,part.Material} )
end

local model = workspace.Building --change this to what the model is
local modelTable = model:Descendants()
for i,v in pairs(modelTable) do
    if v:IsA("Part") or v:IsA("WedgePart") then
        table.insert(StuffWeWantToSave, HttpService:JSONEncode(getPartData(modelTable[v])))
    end
end

将字符串解码为整个模型

这可能会在服务器加载玩家数据时发生。

local HttpService = game:GetService("HttpService")
local SavedStuff = game:GetService("DataStoreService"):GetDataStore("blabla") --I don't know how you save your data, so you'll need to adjust this and the rest of the scripts (as long as you've saved the string somewhere in the player's DataStore)

function createBrick(tab)
    local brick = Instance.new("Part")
    brick.Parent = <insert parent here>
    brick.Size = tab[1]
    brick.Position= tab[2]
    brick.BrickColor= tab[3]
    brick.Material= tab[4]
end

local model = Instance.new("Model") --if you already have 'bases' for the players to load their stuff in, remove this instance.new
model.Parent = workspace

for i,v in pairs(SavedStuff) do
    if v[1] ~= nil then
        CreateBrick(v)
    end
end

FilteringEnabled

如果您的游戏使用启用过滤,请确保只有服务器处理保存和加载数据! (您可能已经知道了)如果您希望玩家通过单击 gui 按钮来保存,请让 gui 按钮触发 RemoteFunction,将其基础数据发送到服务器以将其转换为字符串。

顺便说一句,我不擅长编写脚本,所以我可能在某些地方犯了一个错误......不过祝你好运

【讨论】:

    【解决方案2】:

    Crabway 的回答是正确的,因为 HttpServiceJSONEncodeJSONDecode 方法是解决此问题的方法。正如DataStoreServiceData is ... saved as a string in data stores, regardless of its initial type. (https://developer.roblox.com/articles/Datastore-Errors) 的开发人员参考页面上所说,这解释了您收到的错误,因为您不能简单地将表推送到数据存储;相反,您必须首先使用 JSONEncode 将表的数据编码为字符串。

    虽然我同意 Crabway 的大部分回答,但我相信函数 createBrick 不会按预期运行。考虑以下简单的示例:

    httpService = game:GetService("HttpService")
    t = {
        hello = 1,
        goodbye = 2
    }
    
    s = httpService:JSONEncode(t)
    print(s)
    > {"goodbye":2,"hello":1}
    
    u = httpService:JSONDecode(s)
    for k, v in pairs(u) do print(k, v) end
    > hello 1
    > goodbye 2
    

    如您所见,JSONDecode 返回的表与原始表一样,使用字符串作为键而不是数字索引。因此,createBrick 应该写成这样:

    function createBrick(t)
        local brick = Instance.new("Part")
        brick.Size = t.Size
        brick.Position = t.Position
        brick.BrickColor = t.BrickColor
        brick.Material = t.Material
        -- FIXME: set any other necessary properties.
        -- NOTE: try to set parent last for optimization reasons.
        brick.Parent = t.Parent
        return brick
    end
    

    至于对模型进行编码,调用GetChildren 将生成模型子项的表,然后您可以循环遍历并编码其中所有内容的属性。请注意,在 Crabway 的回答中,他只考虑了 Parts 和 WedgeParts。您应该使用object:IsA("BasePart") 说明所有部分,并使用object:IsA("UnionOperation") 检查联合。以下是一个非常基本的示例,其中我不存储编码数据;相反,我只是想展示如何检查必要的情况。

    function encodeModel(model)
        local children = model:GetChildren()
        for _, child in ipairs(children) do
            if ((child:IsA("BasePart")) or (child:IsA("UnionOperation"))) then
                -- FIXME: encode child
            else if (child:IsA("Model")) then
                -- FIXME: using recursion, loop through the sub-model's children.
            end
        end
        return
    end
    

    对于userdata,例如Vector3s 或BrickColors,您可能希望在使用JSONEncode 对其进行编码时将它们转换为字符串。

    -- Example: part with "Brick red" BrickColor.
    color = tostring(part.BrickColor)
    print(string.format("%q", color))
    > "Bright red"
    

    【讨论】:

      【解决方案3】:

      我建议@Crabway 所说的,使用 HttpService。

      local httpService = game:GetService("HttpService")
      print(httpService:JSONEncode({a = "b", b = "c"}) -- {"a":"b","b":"c"}
      

      但如果您有任何 UserData 值,例如 Vector3s、CFramesColor3s、BrickColors 和 Enum 项目,则使用此 library by Defaultio。其实挺好看的。

      local library = require(workspace:WaitForChild("JSONWithUserdata"))
      library:Encode({Vector3.new(0, 0, 0)})
      

      如果您想要一些文档,请查看脚本中的第一条注释:

      -- Defaultio
      
      --[[
      
          This module adds support for encoding userdata values to JSON strings.
          It also supports lists which skip indices, such as {[1] = "a", [2] = "b", [4] = "c"}
      
          Userdata support is implemented by replacing userdata types with a new table, with keys _T and _V:
              _T = userdata type enum (index in the supportedUserdataTypes list)
              _V = a value or table representing the value
      
          Follow the examples bellow to add suppport for additional userdata types.
      
          ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 
      
          Usage example:
      
              local myTable = {CFrame.new(), BrickColor.Random(), 4, "String", Enum.Material.CorrodedMetal}
      
              local jsonModule = require(PATH_TO_MODULE)
      
              local jsonString = jsonModule:Encode(myTable)
      
              local decodedTable = jsonModule:Decode(jsonString)
      
      --]]
      

      【讨论】:

        猜你喜欢
        • 2021-04-02
        • 2019-06-29
        • 2021-03-07
        • 2023-01-15
        • 2019-05-10
        • 1970-01-01
        • 2020-05-01
        • 2019-07-19
        • 1970-01-01
        相关资源
        最近更新 更多