Build saving system not loading in properly

local datastore= game:GetService("DataStoreService")
local store = datastore:GetDataStore("Buildings")
local saveData = "parts"
local save = {}

wait(5)
for i, v in pairs(workspace:GetChildren()) do
    if v:IsA("BasePart") and v.Name ~= "Baseplate" and v.Name ~= "Terrain" then
    table.insert(save, {v.Size.X, v.Size.Y, v.Size.Z})    
	table.insert(save, {v.CFrame:GetComponents()})
    end
end
print("saved, remove all parts inside workspcae")

store:SetAsync(saveData, save)

wait(5)
for i, v in pairs(store:GetAsync(saveData)) do
	local save = store:GetAsync(saveData)
    local part = Instance.new("Part", workspace)    
    part.Size = Vector3.new(unpack(save[i]))
	part.CFrame = CFrame.new(unpack(save[i+1]))
end
print("loaded")

My goal is simple, this system is supposed to save everything that is in workspace after 5 seconds after the start of the server. However, when I add more than one part inside workspace, it doesn’t work properly. It spawns the bricks fine, however, it also clones the bricks, so putting 3 bricks will spawn 6 bricks. The other bricks that are a clone, spawn at position 0,0,0 with somewhat random sizes. How would I fix it so all bricks spawn at their saved position and at their saved size?

Small video of what I mean:
https://gyazo.com/183c9f2a463decdc80cf5f8963f36fab

2 Likes

The video was small to see but I caught the error after counting the lines. The code at the line of error is the following:

part.CFrame = CFrame.new(unpack(save[i+1]))

The indice [i + 1] in your table save is a nil value or a non-table value, therefore unpack is failing. That would be associated with your saving code,

table.insert(save, {v.CFrame:GetComponents()})

I advise you check what is being pushed to the table, crosscheck between your save and load code, then try again. Whatever the value of i is in your loading code, that indice incremented one place upward is an incorrect value. You might have an improperly formatted DataStore.

That aside, a little bit of a practice problem:

for i, v in pairs(store:GetAsync(saveData)) do
	local save = store:GetAsync(saveData)

You’re unnecessarily spending two requests of your budget to do this. Cache your data to save the amount of DataStore calls and to increase code efficiency.

local save = pcall(store.GetAsync, store, saveData)
for i, v in pairs(save) do
    -- Part set code
end

For each part, you’re saving two tables: the size and CFrame. The loop that recreates the parts is running six times, once for each table. The last iteration produces an error because the last index plus one is out of bounds.

Every even iteration is effectively creating a malformed part because it is using the CFrame components for the size and the next index (the subsequent part’s size) as the CFrame. You could use a numeric for to limit the iterations to odd-numbered indices or reconfigure your data structure to group all of the information into one table per part.