Title pretty much explains it all. I’m trying to create a saving and loading system that takes specific parts from the workspace, and save them, or load them. All parts are unanchored, and some parts have other objects inside them, such as scripts, values, and click detectors. I have no experience with datasore, but i do know that is the only kind of service i can use to create a saving and loading system. Some help will be much appreciated!
You can put them into ServerStorage while you aren’t using them, and bring them back into Workspace when you want them.
Nevermind, after @Invoke_Client’s response I understand the question better.
You would have to use DataStoreService storing the Position of parts in a table
Using the SetAsync function to save the parts position
Using the GetAsync function to load the positions of the parts.
haven’t even used datestores before, i have no idea how they work. Could you possibly provide an example?
Here is an Example, using RemoteEvents
Loading the data
remotes.SaveData.OnServerEvent:Connect(function(player, name, pX, pY, pZ)
local oldData = {}
table.insert(oldData, {Id = name, Position = {X = pX, Y = pY, Z = pZ}})
if dataStore:GetAsync(player.UserId) ~= nil then
for i,v in pairs(dataStore:GetAsync(player.UserId)) do
table.insert(oldData, v)
end
dataStore:SetAsync(player.UserId, oldData)
else
dataStore:SetAsync(player.UserId, oldData)
end
end)
Saving the data
game.Players.PlayerAdded:Connect(function(plr)
for i,v in pairs(dataStore:GetAsync(plr.UserId)) do
print("| Name: " .. v.Id .. "\n| ['X'] Position: " .. v.Position.X .. "\t| ['Y'] Position: " .. v.Position.Y .. "\t| ['Z'] Position: " .. v.Position.Z)
local part = replicatedStorage:WaitForChild("Shared Instances")["Placement Storage"][v.Id]:Clone()
part.Parent = workspace.Plots["1"].Building
part.Position = Vector3.new(v.Position.X, v.Position.Y, v.Position.Z)
end
end)
Note: The v.Id is basically you’ll need a Reference to the part in the server.
Here’s a small example of saving data using datastore.
PartsArray = {true} -- the data you want to store
DataStoreService = game:GetService("DataStoreService")
local UserId = 2446384 -- the userid of the user you want to save to
local PartStorage = DataStoreService:GetDataStore("PartSaves", UserId)
PartStorage:SetAsync("PartSave",PartsArray)
print(PartStorage:GetAsync("PartSave")[1]) --> true
GetAsync is not a valid member of DataStoreService, what do i do?
I also got this error: ServerScriptService.LoadAndSave:2: bad argument #1 to ‘pairs’ (table expected, got no value)
Make sure you’re using GetAsync on the DataStore itself, not on DataStoreService!
i did that and i got this error: ServerScriptService.LoadAndSave:2: bad argument #1 to ‘pairs’ (table expected, got no value)
Let me see your code, that’s the only way I can properly diagnose the issue
replicatedStorage = game:GetService("ReplicatedStorage")
LoadEvent = replicatedStorage:WaitForChild("LoadEvent")
SaveEvent = replicatedStorage:WaitForChild("SaveEvent")
LoadEvent.OnServerEvent:Connect(function(player, name, pX, pY, pZ)
dataStore = game:GetService("DataStoreService"):GetDataStore(player.UserId)
local oldData = {}
table.insert(oldData, {Id = name, Position = {X = pX, Y = pY, Z = pZ}})
if dataStore:GetAsync(player.UserId) ~= nil then
for i,v in pairs(dataStore:GetAsync(player.UserId)) do
table.insert(oldData, v)
end
dataStore:SetAsync(player.UserId, oldData)
else
dataStore:SetAsync(player.UserId, oldData)
end
end)
SaveEvent.OnServerEvent:Connect(function(plr)
dataStore = game:GetService("DataStoreService"):GetDataStore(plr.UserId)
for i,v in pairs(dataStore:GetAsync(plr.UserId)) do
print("| Name: " .. v.Id .. "\n| ['X'] Position: " .. v.Position.X .. "\t| ['Y'] Position: " .. v.Position.Y .. "\t| ['Z'] Position: " .. v.Position.Z)
local part = replicatedStorage:WaitForChild("Shared Instances")["Placement Storage"][v.Id]:Clone()
part.Parent = workspace.Plots["1"].Building
part.Position = Vector3.new(v.Position.X, v.Position.Y, v.Position.Z)
end
end)
You’re not doing a sanity check for GetAsync - you need to make sure that GetAsync doesn’t return nil (it returns nil if there’s no data)
You should also be wrapping your datastore calls in pcalls, but it isn’t necessary
I’d save the CFrames
of each part that you want to save and store it as a table in a datastore. Position is a Vector3
and doesn’t account for rotation. Best of luck!
Expanding on this, because you want to save parts in general you should save all of the properties that you would need.
Some vital properties that might be important to save (in general) are:
- CFrame (position + orientation in one)
- Color (you need to serialize this)
- Size
- Material (I believe you need to serialize this)
Still depends on your use case though
im working on a classic styled building games, there are many diffirent parts too. some also do stuff, like move using a body thrust, or be clickable. Similar to an older game that sharky99 made
(i know i am little late, but i am going to post anyways),
Datastore
As Far as Datastores go there are pretty fun(at least for me) and there are alot of resources(below) to help you understand them, here’s a quick example nonetheless:
(Saving)
---this example is using update async( there are 3 other ones to use)
local DataStoreService = game:GetService("DataStoreService")
local MyStore = DataStoreService:GetDataStore("Test")
local Key = player --Our Scope, the key, we want to save our data under
MyStore:UpdateAsync(Key, function(prev)----unlike other Datstore functions(like SetAsync), this one returns the previously saved value to our key
if prev == nil then
prev = {}
end
local RandomNumber = math.random(1,50)
table.insert(prev, #prev + 1, RandomNumber)
return prev --- Update Async, essentially is looking for a returned value, to, well update our previous value to! (in this case we "overwrite" our table with a newer version of our table
end
(loading data)
local DataStoreService = game:GetService("DataStoreService")
local MyStore = DataStoreService:GetDataStore("Test")
local Key = player --Our Scope, the key, we want to save our data under
--This time we are going to use Get Async to get our data
local success, result = pcall function() --- pcalls are pretty handy when working with datastore, they "don't" error and just return wether the code inside of it worked and the result
local data = MyStore:GetAsync(key) --- All we need to put here is our player (key) to get the table saved above
end
Saving Parts
There are a few ways of saving parts, some people choose to save parts( positions of parts not actual parts) under a table and use non-string indices( which i find to be one of the better ways) . Note that parts can not be directly saved to a Datastore, and therefor a string or number indicating which part needs to cloned needs to be passed. Keep in mind that if you were to save many parts, there is a chance you could run into the Datastore limit (one of which is 260,000 characters per key) , which is why you should only save necessary things. Saving the parts’ position is an example of a necessary thing, however something like the size might not(depending on your game). So if i were making a building game for example, to save parts i would only save the string/number associated with an object i could clone, from let’s say the replicated storage, and i would only save the position and the color of the part
(Recommend (more) Practice)
local PartToSave = {
[1] = "ACoolPart"
[2] = 0,0,0 ----As a Note, you cannot save color3s as it is not a valid in UTF-8 terms
[3] = {50,-70,100}
}
(Not recommend Practice)
local PartToSave = {
["Name"] = "ACoolPart"
["Color"] = 0,0,0 --String index
["Position"] = {50,-70,100}
}
Compression Techniques/Safe Saving?
Safe saving and being compact is important when creating building systems, for compression you could go and even use numbers to represent different variations of parts(recommend), if you wanted to you could use compression techniques (in resources), or you could just use some other techniques like the theoretical one mentioned here:
https://devforum.roblox.com/t/using-multiple-data-stores-for-more-capacity/356256
(i have not personally used this one but it might be good to check it out if you want to)
Resources
Stravant's BitBuffer Module - Compact Storage Of Data [Tutorial]
Details on DataStoreService for Advanced Developers
Data Stores | Documentation - Roblox Creator Hub
GlobalDataStore | Documentation - Roblox Creator Hub
Lua Globals | Documentation - Roblox Creator Hub – pcalls are lua globals
Stop using SetAsync() to save player data – this is a good read
Videos:
https://www.youtube.com/watch?v=DkYupSBUpes
https://www.youtube.com/watch?v=I4A9qosS9xo
https://www.youtube.com/watch?v=Nfm-CtRUNqk – a little old but should still work!
Other:
How to save Dictionary using DataStore2? - #4 by Operatik
Handling sandbox tycoon data —Have not tested
Should i be concerned with the datastore data limit? - #9 by Vivid_Void
Creating A Furniture Placement System --At the bottom Ego Moose does a pretty good job of explaining saving placement system data (its brief but still)
Hay, this is probably late, but this might help as well!