我正在尝试制作一个游戏,让玩家创建自己的建筑物,然后可以将其保存以供其他玩家观看和玩。但是,roblox不允许我存储整个创作所需的所有数据(每个积木有多个属性) 我得到的只是这个错误代码: 104:无法在DataStore中存储数组
任何帮助将不胜感激!
答案 0 :(得分:0)
我不确定这是否是最好的方法,但这是我的尝试。下面是一个表的示例,您可以使用表存储多个值。我认为您可以使用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
FilteringEnabled
如果您的游戏使用了启用过滤功能,请确保只有服务器才能处理保存和加载数据! (您可能已经知道)如果您想让播放器通过单击gui按钮保存,请使gui按钮触发一个RemoteFunction,将其基础数据发送到服务器以将其转换为字符串。
顺便说一句,我不太擅长编写脚本,所以我可能在某些地方犯了一个错误。.祝你好运
答案 1 :(得分:0)
Crabway的答案是正确的,因为HttpService
的{{1}}和JSONEncode
方法是解决此问题的方法。正如在JSONDecode
,DataStoreService
(https://developer.roblox.com/articles/Datastore-Errors的开发人员参考页上所说的那样。)这说明了您收到的错误,因为您不能简单地将表推入数据存储中。相反,您必须首先使用Data is ... saved as a string in data stores, regardless of its initial type.
将表的数据编码为字符串。
尽管我同意Crabway的大部分回答,但我相信函数JSONEncode
的行为可能不符合预期。考虑下面的简单示例:
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
会产生一个模型子表,然后您可以循环浏览并编码其中的所有属性。请注意,在Crabway的答案中,他仅占GetChildren
和Part
的部分。您应该使用WedgePart
来说明所有零件,还应该使用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
,当您使用BrickColor
对其进行编码时,您可能希望将它们转换为字符串。
JSONEncode
答案 2 :(得分:0)
我建议@Crabway说什么,使用HttpService。
local httpService = game:GetService("HttpService")
print(httpService:JSONEncode({a = "b", b = "c"}) -- {"a":"b","b":"c"}
但是,如果您有任何UserData值,例如Vector3
,CFrames
,Color3
,BrickColor
和Enum
个项目,请使用此{ {3}}。真的很好。
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)
--]]