Roblox - как хранить большие массивы в хранилищах roblox - PullRequest
0 голосов
/ 24 сентября 2018

Я пытаюсь создать игру, в которой игроки создают свои собственные здания, а затем могут сохранить их, чтобы другие игроки могли их видеть и играть.Тем не менее, roblox не позволяет мне хранить все данные, необходимые для всего создания (для каждого кирпича есть несколько свойств) Все, что я получаю, это код ошибки: 104: Не удается сохранить массив в хранилище данных

, любая помощь можетс благодарностью!

Ответы [ 2 ]

0 голосов
/ 16 июня 2019

Ответ Крэбвея верен в том, что методы 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.

Хотя я согласен с большей частью ответа Крэбвея, я считаю, что функция 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 и * 1022.* 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"
0 голосов
/ 25 сентября 2018

Я не уверен, что это лучший метод, но это моя попытка.Ниже приведен пример таблицы, вы можете использовать таблицы для хранения нескольких значений.Я думаю, что вы можете использовать функцию 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

Если ваша игра использует filteringenabled, убедитесь, что только сервер обрабатывает сохранение и загрузкуданные!! (вы, вероятно, уже это знали) Если вы хотите, чтобы проигрыватель сохранял нажатием кнопки графического интерфейса, заставьте кнопку графического интерфейса вызывать функцию RemoteFunction, которая отправляет данные своей базы на сервер, чтобы преобразовать ее в строку.

КСТАТИ IЯ не настолько хорош в написании сценариев, так что я, вероятно, когда-то допустил ошибку ... удачи, хотя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...