How do I save a CFrame of a model?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I want to save CFrame of a part relative to the plot.
  2. What is the issue? Include screenshots / videos if possible!
    I am not exactly sure how to get the CFrame relative to the plot and save it.
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I tried using :ToObjectSpace() and :ToWorldSpace() but I was not sure how to apply it or what it does.
    I also tried doing this:
local function savePlayerData(player)
	local plotNumber = player.leaderstats.Plot
	if plotNumber == 0 then return end
	local pplot = game.Workspace:FindFirstChild("Plot"..plotNumber.Value)
	
	print(player)
	local placedObjects = {}
	print(player.Name.."'s Blocks")
	for _, loop in ipairs(workspace:WaitForChild(player.Name.."'s Blocks"):GetChildren()) do
		local objInfo = {   
			loop.Name,
			--Position
			loop.PrimaryPart.Position.X - pplot.Position.X,
			loop.PrimaryPart.Position.Y - pplot.Position.Y,
			loop.PrimaryPart.Position.Z - pplot.Position.Z,
			--Orientation/Rotation
			loop.Rotation.Value.X - pplot.Orientation.X,
			loop.Rotation.Value.Y - pplot.Orientation.Y,
			loop.Rotation.Value.Z - pplot.Orientation.Z
			--tostring()(pplot.CFrame:ToObjectSpace(loop.PrimaryPart.CFrame))
		}
		
		table.insert(placedObjects, objInfo)
	end
	
	local encodedthing = HttpTHing:JSONEncode(placedObjects)
	print(encodedthing)
	local data = {
		player.leaderstats.Cash.Value;
		encodedthing
	}
	--Start of Test
	print(typeof(placedObjects))
	print(typeof(data[2]))
	
	--local Decodedthing = HttpTHing:JSONDecode(data[2])
	--print(typeof(Decodedthing))
	--print(Decodedthing)
	--print(data[2])
	--print(unpack(Decodedthing))
	----table.insert(data, 2, encodedthing)
	--print(data)
	--End of Test
	local sucess, err = pcall(function()
		dataStore:SetAsync(player.UserId, data)
		print("hi")
	end)
	print(sucess)
	print("hi")
	if sucess then
		print("Data Saved!")
	else
		print("Data failed to save, trying again!")
		local sucess, err = pcall(function()
			dataStore:SetAsync(player.UserId, data)
		end)
		warn(err)
	end
end

To save and this:

game.Players.PlayerAdded:Connect(function(player)
	local blkctnr = Instance.new("Folder", workspace)
	blkctnr.Name = player.Name.."'s Blocks"
	

	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"

	local cash = Instance.new("IntValue", leaderstats)
	cash.Name = "Cash"
	
	local plot = Instance.new("IntValue", leaderstats)
	plot.Name = "Plot"

	
	repeat
		wait()
	until plot.Value ~= 0 or player == nil
	
	local data = {}
	local sucess, err = pcall(function()
		data = dataStore:GetAsync(player.UserId)
	end)
	if sucess and data then
		print("Data Loaded!")
		cash.Value = data[1]
		
	else
		print("No data was found for this player, trying again!")
		local sucess, err = pcall(function()
			data = dataStore:GetAsync(player.UserId)
		end)
		if sucess and data then
			print("The data was found!")
			cash.Value = data[1]
			
		else
			print("Data cannot be found")
			cash.Value = 500
			
		end
	end
	
	local plot = workspace:WaitForChild("Plot"..plot.Value)
	print(data[2])
	local Decodedthing = HttpTHing:JSONDecode(data[2])
	print(Decodedthing)
	for _, struc in ipairs(Decodedthing) do
		local thing = game.ServerStorage:WaitForChild(struc[1]):Clone()
		
		thing.Parent = blkctnr
		if struc[1] == "BasicCollector" then
			thing.Collector.Owner.Value = player.Name
		end
		thing.Rotation.Value = Vector3.new(struc[5], struc[6], struc[7])
		
		
		local CframeCompoList = string.split(struc[2], ",")
		table.remove(struc, 1)
		
		
		
		local rotatev = plot.Orientation + Vector3.new(struc[4], struc[5], struc[6])
		
		thing:SetPrimaryPartCFrame(CFrame.new(plot.Position + Vector3.new(struc[1], struc[2], struc[3])) * CFrame.Angles(math.rad(rotatev.X), math.rad(rotatev.Y), math.rad(rotatev.Z)))
		thing.PrimaryPart.Orientation = Vector3.new(0, 0, 0)

	end
	
	player.CharacterAdded:Connect(function(character)
		wait(1)
		character.HumanoidRootPart.CFrame = CFrame.new(workspace:FindFirstChild("Plot"..plot.Value).Position + Vector3.new(0, 100, 0))
	end)
	while true do
		wait(20)
		savePlayerData(player)
	end

end)

To load the progress/models but it worked with the position but it did not put it relative to the plot (like on the left or right side of the plot) and the orientation was not right (like at all)

I have also tried looking in the DevForum but I either did not get it or it did not work.

How would I do this?

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

Tell me if any more information is needed! :slightly_smiling_face:

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

1 Like

Actually I think the only thing that I don’t get now is how to save a CFrame, can someone explain how to do that?

add a primarypart to the model u want to save on then use the GetPrimaryPartCFrame(model) function to get the cframe of that model, then from there u can encode, decode it so it can be saved into datastores,

By that do you mean encoding the components or the CFrame itself?

What you can do to save the CFrame is get its components and save it as a string:

local function getCFrameAsString(cframe)
    return table.concat({cframe:GetComponents()},",")
end

When loading in the data, you turn it back into a CFrame with this function:

local function getCFrameFromString(str) 
    return CFrame.new(table.unpack(str:split(",")))
end
4 Likes

To get the CFrame relative to the plot you can do:

local RelativeCFrame = Part.CFrame * Plot.CFrame:Inverse();

and you can save it with the method @dukzae provided.

1 Like

I tried doing this:

table.concat({(loop.PrimaryPart.CFrame * pplot.CFrame:Inverse()):GetComponents()}, ",")
thing:SetPrimaryPartCFrame(CFrame.new(table.unpack(string.split(struc, ","))))

but it gave this error:

16:59:43.645  ServerScriptService.Script:140: invalid argument #1 to 'split' (string expected, got table)  -  Server - Script:140
  16:59:43.645  Stack Begin  -  Studio
  16:59:43.645  Script 'ServerScriptService.Script', Line 140  -  Studio - Script:140
  16:59:43.645  Stack End  -  Studio

Do you know why this happened?

Well, now it kind of works? It load and saves, but it is saving and loading in the wrong spots! Although, they do have the right orientation. Why is this happening?

You can get the components of the model’s pivot position, put them into a table and save the table.

Once you want to load that data you would construct a new cframe and put the components unpacked inside the arguments and set the model’s pivot.

I have not tested this method yet.

Now it is loading in the right spots, but it has the wrong orientation. This is the code:

--Saving
table.concat({(pplot.CFrame:ToObjectSpace(loop.PrimaryPart.CFrame)):GetComponents()}, ",")
--Loading
thing:SetPrimaryPartCFrame(plot.CFrame:ToWorldSpace(CFrame.new(table.unpack(string.split(struc[1], ",")))))

How do I fix it?

1 Like

Wait, I found out that I put the wrong orientation, I think it works, thank you everyone for your help!