I have learned how to make a save system for my sandbox tycoon I am working on but can't seem to get the saved data to load on to the correct plot with zero offset (What I mean by offset is that it is not aligned with the plot. It's slightly off if the plot). My save function looks like this:
The script is located in Workspace and it is a server script. It is not disabled.
local function Save(plr) local key = "plr-"..plr.UserId local TycoonSave = {} local Tycoon = script.Parent.SaveFolder:GetChildren() for i, obj in pairs(Tycoon) do if obj then table.insert(TycoonSave, { ["Name"] = obj.Name; ["CFS"] = { -- CFS = CFrames ["X"] = obj.PrimaryPart.CFrame.X; ["Y"] = obj.PrimaryPart.CFrame.Y; ["Z"] = obj.PrimaryPart.CFrame.Z; ["R"] = obj.PrimaryPart.Orientation.Y } }) end end local success, err = pcall(function() DataStore:SetAsync(key, TycoonSave) end) if not success then warn("Failed to over-right data"..tostring(err)) return end return TycoonSave end
When I load my data back in I have tried adding and multiplying the plots CFrame to the models but that gave me and offset of about 10 studs on every axis except Y. Here is an example of the load function:
local function Load(plr) local key = "plr-"..plr.UserId local Saved local success, err = pcall(function() Saved = DataStore:GetAsync(key) end) if not success then warn("Failed to read data"..tostring(err)) return end if Saved then for q, objs in pairs(script.Parent.SaveFolder:GetChildren()) do if objs then objs:Destroy() end end wait(1) for i, obj in pairs(Saved) do if obj then local SavedModel = game.ReplicatedStorage.Models:FindFirstChild(obj.Name) if SavedModel then wait(0, 1) local Model = SavedModel:Clone() Model.Parent = workspace.SaveFolder if Model then Model:SetPrimaryPartCFrame(Plot.CFrame * CFrame.new(obj.CFS.X, obj.CFS.Y, obj.CFS.Z) * CFrame.Angles(0, math.rad(obj.CFS.R), 0)) Model.PrimaryPart.Transparency = 1 Model.PrimaryPart.CanCollide = false end end end end wait(1) else -- save the data end
I call the save function when the player clicks a button and when the player leaves. The load function is called when the player joins. The two functions are in one script.
Thanks for the help!
Alright Creeperman1524 has told you how to this sort of. What he means is, instead of saving data like you are current with primarypartcframe and doing alot of math, i would use ":PointToObjectSpace" on the cframe value, heres sortof how you would do it(it does return vector3). "PointToObjectSpace" gets the vector3 position from the plot, and then you would do "PointToWorldSpace" to place the objects once data is loaded.
--PointToObjectSpace()
heres the save function:
local function Save(plr) local key = "plr-"..plr.UserId local TycoonSave = {} local Tycoon = script.Parent.SaveFolder:GetChildren() for i, obj in pairs(Tycoon) do if obj then table.insert(TycoonSave, { ["Name"] = obj.Name; ["CFS"] = { -- CFS = CFrames ["X"] = Plot.CFrame:PointToObjectSpace(obj.PrimaryPart.CFrame.p).X; ["Y"] = Plot.CFrame:PointToObjectSpace(obj.PrimaryPart.CFrame.p).Y; ["Z"] = Plot.CFrame:PointToObjectSpace(obj.PrimaryPart.CFrame.p).Z; ["R"] = obj.PrimaryPart.Orientation.Y } }) end end local success, err = pcall(function() DataStore:SetAsync(key, TycoonSave) end) if not success then warn("Failed to over-right data"..tostring(err)) return end return TycoonSave end
and heres the load:
local function Load(plr) local key = "plr-"..plr.UserId local Saved local success, err = pcall(function() Saved = DataStore:GetAsync(key) end) if not success then warn("Failed to read data"..tostring(err)) return end if Saved then for q, objs in pairs(script.Parent.SaveFolder:GetChildren()) do if objs then objs:Destroy() end end wait(1) for i, obj in pairs(Saved) do if obj then local SavedModel = game.ReplicatedStorage.Models:FindFirstChild(obj.Name) if SavedModel then wait(0, 1) local Model = SavedModel:Clone() Model.Parent = workspace.SaveFolder if Model then Model:SetPrimaryPartCFrame(CFrame.new(Plot.CFrame:PointToWorldSpace(Vector3.new(obj.CFS.X, obj.CFS.Y, obj.CFS.Z).X,Plot.CFrame:PointToWorldSpace(Vector3.new(obj.CFS.X, obj.CFS.Y, obj.CFS.Z).Y,Plot.CFrame:PointToWorldSpace(Vector3.new(obj.CFS.X, obj.CFS.Y, obj.CFS.Z).Z)*CFrame.Angles(0, math.rad(obj.CFS.R), 0)) Model.PrimaryPart.Transparency = 1 Model.PrimaryPart.CanCollide = false end end end end wait(1) else -- save the data end
This should work, all i did was replace all that math you did when loading to PointToWorldSpace, after saving it from the last plot with PointToObjectSpace. Hope this helps you