How would I save a name and position in one data store?

So I am making an open world game with building mechanics. I want to make a saving system which not only saves the name of the Model (in order to find which building the player placed) but also saves the CFrame of the primary part (to position it exactly where the player placed it on their last playthrough).

I have tried saving a table in the data store which contains both the name and position of every structure placed, though it comes out with an error message which states that arrays cannot be saved in data stores.

Here is the code which runs upon the player joining:

--DataStore Setup

local playerId = "plr_"..plr.UserId
local structuresData

local success, errorMessage = pcall(function()
	structuresData = structuresStore:GetAsync(playerId)
end)
--Succesfully Loaded Player Values

if success then
	if structuresData then
		for i, v in pairs(structuresData) do
			local structureName = v[1]
			local structureCFrame = v[2]
			local savedStructure = structuresFolder:FindFirstChild(structureName)
			local clonedStructure = savedStructure:Clone()
			
			clonedStructure:SetPrimaryPartCFrame(structureCFrame)
			clonedStructure.Parent = placedBlueprints
		end
	end
end

And here is the code which runs upon the player leaving:
local playerId = ā€œplr_ā€ā€¦plr.UserId

local success, errorMessage = pcall(function()
	--Save Placed Structures and CFrame

	local playerStructures = {}
	for i, v in pairs(placedBlueprints:GetChildren()) do
		if v:IsA("Model") then
			local primaryPart = v.PrimaryPart
			table.insert(playerStructures, {v.Name, primaryPart.CFrame})
		end
	end
	structuresStore:SetAsync(playerId, playerStructures)
	
end)

--Check If Save Was Succesful

if success then
	print(plr.Name.."'s data saved")
else
	warn(errorMessage)
	print(plr.Name.."'s data could not save")
end
1 Like

That error is misleading, what the error is actually trying to say is that it canā€™t serialize the CFrame value to JSON. You can only store strings, booleans, numbers and tables that contain these data types.

To get around this, you need to get the components of CFrame with CFrame:GetComponents when creating the table that will be stored in the datastore:

table.insert(playerStructures, {v.Name, primaryPart.CFrame:GetComponents()})

and recreate the CFrame from those components with CFrame.new when deserializing the data:

local structureCFrame = CFrame.new(table.unpack(v, 2, 13))
2 Likes

Thanks so much! This seemed to have worked. Quick question out of curiosity though, what does the 13 represent in the ā€˜table.unpackā€™ function?

CFrame:GetComponents() returns 12 numbers and since we store the modelā€™s name at the first entry of the array, we need to tell table.unpack to start unpacking from 2nd entry and stop at 13th entry. That 13 represents which entry table.unpack will stop at.

1 Like

Ahh I see. Again, thanks so much :slight_smile: