How can i save the models in workspace using DataStoreService?

Hello, I am developing a single player game in which the player gets to place models into the Workspace, but I need to make it so every 60s or such the game saves which objects are in the assigned PlayerBuildings folder in Workspace. I found this script, but it only works on parts, does anyone know how I could adapt this code to save models?

Script in Workspace

local playerDataStore = game:GetService("DataStoreService"):GetDataStore("PlayerData")

local function savePlayerData(player)
	local playerKey = "player_"..player.UserId
	local playerData = {}
	for _, part in ipairs(game.Workspace.PlayerBuildings:GetChildren()) do
		playerData[part.Name] = {
			Position = part.Position,
			Rotation = part.Rotation,
			Color = part.Color,
			Size = part.Size,
			Material = part.Material
		}
	end
	local success, err = pcall(function()
		playerDataStore:SetAsync(playerKey, playerData)
	end)
end

local function loadPlayerData(player)
	local playerKey = "player_"..player.UserId
	local playerData

	local success, err = pcall(function()
		playerData = playerDataStore:GetAsync(playerKey)
	end)
	if playerData then
		for partName, partData in ipairs(playerData) do
			local newPart = Instance.new("Model")
			newPart.Position = partData.Position
			newPart.Rotation = partData.Rotation
			newPart.Color = partData.Color
			newPart.Material = partData.Material
			newPart.Size = playerData.Size
		end
	end
end

game.Players.PlayerAdded:Connect(function(player)
	loadPlayerData(player)

	player.PlayerGui:WaitForChild("Save").Save.MouseButton1Click:Connect(function()
		savePlayerData(player)
	end)
end)
2 Likes

Hello, there !
What you’ve to do is basically replacing part’s properties by model’s.
As well, edit the following things:
part.Position model.PrimaryPart.Position
part.Rotation model.PrimaryPart.Orientation
part.Color model.PrimaryPart.Color
part.Size model.GetScale()
part.Material model.PrimaryPart.Material
Do the same for partData

Don’t forget to set a part as the primary part of your model, in other cases, it won’t work.
If you want the color of each part of your model, you’ll need to loop the corresponding step for the number of parts in your model and to store them in an array. This is the method I’d rather use, but I’m not sure it’s the best. Maybe a function exists for this, but I sadly don’t know it yet.

Don’t hesitate if you have other questions or if something is wrong with what I said.
Hoping I could satisfy you.
Have a great day!

1 Like

It didn’t work, I got an error saying I couldn’t store Dictionary in date store.

My script

local playerDataStore = game:GetService("DataStoreService"):GetDataStore("PlayerData")

local function savePlayerData(player)
	local playerKey = "player_"..player.UserId
	local playerData = {}
	for _, model in ipairs(game.Workspace.PlayerBuildings:GetChildren()) do
		playerData[model.Name] = {
			Position = model.PrimaryPart.Position,
			Rotation = model.PrimaryPart.Rotation,
			Color = model.PrimaryPart.Color,
			Size = model:GetScale(),
			Material = model.PrimaryPart.Material
		}
	end
	local success, err = pcall(function()
		playerDataStore:SetAsync(playerKey, playerData)
	end)
end

local function loadPlayerData(player)
	local playerKey = "player_"..player.UserId
	local playerData

	local success, err = pcall(function()
		playerData = playerDataStore:GetAsync(playerKey)
	end)
	if playerData then
		for modelName, modelData in ipairs(playerData) do
			local newmodel = Instance.new("mode")
			newmodel.Position = modelData.PrimaryPart.Position
			newmodel.Rotation = modelData.PrimaryPart.Rotation
			newmodel.Color = modelData.PrimaryPart.Color
			newmodel.Material = modelData.PrimaryPart.Material
			newmodel.Size = playerData.PrimaryPart:GetScale()
		end
	end
end

game.Players.PlayerAdded:Connect(function(player)
	loadPlayerData(player)

	player.PlayerGui:WaitForChild("Save").Save.MouseButton1Click:Connect(function()
		savePlayerData(player)
	end)
end)
2 Likes

you have to like encrypt it or something, something like that json thingie

1 Like

Try encoding the table via HttpService:JSONEncode(tableHere). If you want to get the table the way it was before, you would use game.HttpService:JSONDecode(stringHere)

Also special values like Vector3, Color3, and CFrames don’t have a way to be stored in tables if they are going to be encoded into string format. Only null, String, Number, Arrays, and Dictionaries. I recommend using these two functions when it comes to carrying over these values.

-- Convert Vector3s and Color3s into tables
function preserveSpecialValues(t)
	local new = {}
	
	local function a(lt,nt)
		for i,v in pairs(lt) do
			if type(v) == 'table' then
				nt[i] = {}
				a(v,nt[i])
			else
				if typeof(v) == 'Vector3' then
					nt[i] = {type='Vector3', params={v.X, v.Y, v.Z}}
				elseif typeof(v) == 'Color3' then
					nt[i] = {type='Color3', params={v.R, v.G, v.B}}
				elseif typeof(v) == 'EnumItem' then
					nt[i] = v.Name
				end
			end
		end
	end
	a(t,new)
	
	return new
end
-- Convert supported tables back into Vector3s and Color3s.
function obtainSpecialValues(t)
	local new = {}

	local function a(lt,nt)
		for i,v in pairs(lt) do
			if type(v) == 'table' then
				nt[i] = {}
				if not v.type then
					a(v,nt[i])
				else
					if v.type == 'Vector3' then
						nt[i] = Vector3.new(table.unpack(v.params))
					elseif v.type == 'Color3' then
						nt[i] = Color3.new(table.unpack(v.params))
					end
				end
			else
				nt[i] = v
			end
		end
	end
	a(t,new)

	return new
end
2 Likes

The reason is because you are trying to save colour which you cannot do - try saving the individual R, G, B values for example


local save = {

R = 0,
G = 205,
B = 1
}
2 Likes

How would i implement this? Im really not familiar with save systems

Instead of part.Color do

local saveTable = {
   Color = {}
   Rotation = {}
   Size = {}
   Position = {}
}

and for material you dont have to put it as a table just save part.Material
(inside each color, rotation etc u put each xyz or rgb values)