我试图做一个游戏,玩家创造自己的建筑,然后可以保存他们为其他玩家看到和发挥。但是,roblox不允许我存储整个创建所需的所有数据(每个块都有几个属性),我得到的全部错误代码是: 104:无法在DataStore中存储数组
任何帮助都将不胜感激!
发布于 2018-09-25 02:19:46
我不确定这是不是最好的方法,但这是我的尝试。下面是一个表的示例,您可以使用表来存储多个值。我认为您可以使用HttpService的JSONEncode函数将表转换为字符串(希望能够更有效地保存)。
JSONEncode (将布里克的数据放入字符串中,您可以将其保存到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中。
将整个模型编码为字符串
如果你的玩家的“建筑”是一个模型,你可以使用上面的代码脚本将模型中的所有部分转换成一个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,该将其基数据发送到服务器,并将其转换为字符串。
顺便说一句,我不太擅长编写脚本,所以我可能犯了一个错误。祝你好运
发布于 2019-06-15 21:25:49
克拉布韦的回答是正确的,因为HttpService
的JSONEncode
和JSONDecode
方法是解决这个问题的方法。正如它在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的回答中,他只说明了Part
s和WedgePart
s。您应该说明使用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
(如Vector3
s或BrickColor
s ),当您使用JSONEncode
对它们进行编码时,您可能希望将这些字符串转换为字符串。
-- Example: part with "Brick red" BrickColor.
color = tostring(part.BrickColor)
print(string.format("%q", color))
> "Bright red"
发布于 2019-10-03 20:40:36
我建议使用@Crabway说的,使用HttpService。
local httpService = game:GetService("HttpService")
print(httpService:JSONEncode({a = "b", b = "c"}) -- {"a":"b","b":"c"}
但是,如果您有任何UserData值,如Vector3
s、CFrames
、Color3
s、BrickColor
s和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)
--]]
https://stackoverflow.com/questions/52485973
复制相似问题