Roblox - 如何在 roblox 数据存储中存储大型阵列



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

任何帮助将不胜感激!

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

JSONEncode(将砖块的数据放入字符串中,您可以将其保存到数据存储中

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 中。

将整个模型编码为字符串

假设玩家的"建筑"是一个模型,您可以使用上面的编码脚本将模型内的所有部分转换为 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

筛选已启用

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

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

克拉布韦的回答是正确的,因为HttpServiceJSONEncodeJSONDecode方法是解决这个问题的方法。正如DataStoreService的开发人员参考页面上所说,Data 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"

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

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

但是,如果您有任何 UserData 值,例如Vector3s、CFramesColor3s、BrickColors 和Enum项,则按 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)
--]]

最新更新