I hope this video has helped in some way. If you have any questions or problems, join the discord server: discord.gg/xJB2Adu4cr. Another way to reach me for dev support related questions is to @ me in a dev forum post. Thanks for watching, hope it helped!
great tutorial! personally, i used setasync() instead of updateasync() because of updateasync being slower and sending more api requests. to anyone reading this, keep this in mind!
ty i used to not know how to do datastore for folder i used to think it was so consufing and i finally did it (lil dif frm urs it was just a plr folder i put there and yea) tysm 👍
oml frigging thank you. ive been searching for this FOR HOURSSSS!!!! i frigging luv u words cannot express how much pain and suffering i was in for THESE YEARS i frigging luv u
can you implement a saving system into the placement system? it would really be helpful because i'm making a game kind of like mini cities. everything works I just need it to save but I don't know how to do it. if you had time to implement a saving system kind of like this but works with the placement system series you made, it would be awesome. thanks
aha, thank you, this is very well explained. I think im missing some context: am i right in thinking that this solution would be useful when making a placement system (of parts)? right now however, the relevant parts are in the datahandler... would i be correct thinking that 1. this is the place a placement system would save parts to? (which then are saved to the datastore when a player leaves) 2. if you wanted parts to not be linked to a player so much as to a server, then the starting signal shouldn't be playeradded but server startup (if that is something that exists)? I have read quite a lot and watched videos on datastores, but not proficient yet, please excuse me if im not getting things right. thank you for your response in advance
why do you need to put in the x y z seperately? cant we do obj.CFrame.Position instead of obj.CFrame.Position.X obj.CFrame.Position.Y obj.CFrame.Position.Z?
i get error: DataStoreService: CantStoreValue: Cannot store Array in data store. Data stores can only accept valid UTF-8 characters. API: UpdateAsync, Data Store: SBGObjectsData
Awesome! Is there away to save gui data. Like if someone wanted to mute music in the game and they go to the settings to turn it off then once they leave it saves it and when they join the music is muted.
You can save a boolean so True or False then retrieve that data when they join and if its True then enable the music, if its False then disable it. (Once player clicks music setting button fire an remote event to change the value in datastore, just make sure the arguments are Boolean so you just pass in True or False when firing.)
how can you save the brickcolor? i've tried many ways but it keeps on putting in the wrong type of color to each part. Could u please help me out? Please respond asap.
may you tell me how do you run it by a gui like save button? if you press the button it will save your parts, also for the load button too and make multiple buttons for other buildings and different stuff
IS this possible with gui objects in a tag? Because i want to save the visibility of the gui object, in my case a button and a text label. But how can i achieve that?
hey mate! Im a little nooby dev, wanted to ask how to save the position of a model inside a limited position like ex: a restaurant tycoon you place stuff and you save it bt there are dif spots and want them to spawn like you want to
Do you mean saving positions relative to a plot? If so, what you can do is utilize the CFrame library to convert your positions to local space (aka object space). You can use the Inverse() method to convert the CFrame: for i, item in ipairs(plot.itemHolder:GetChildren()) do -- Get 'local' positions and rotation local objCFrame = plotCFrame:Inverse()*item.PrimaryPart.CFrame local _, angle = objCFrame:ToOrientation() -- Add values to table table.insert(data, { tostring(item), objCFrame.X, objCFrame.Y, objCFrame.Z, math.round(angle*(180/math.pi)) }) end That will save the data relative to the plot chosen. To load in, you can reverse the process by simply multiplying the plot CFrame and the objects CFrame to convert back to world coordinates: for i, item in ipairs(savedData) do local newItem = items:FindFirstChild(item[1]):Clone() if newItem then local x = item[2] local y = item[3] local z = item[4] local yAngle = item[5]*math.pi/180 local angle = CFrame.fromEulerAnglesXYZ(0, yAngle, 0) local pos = plotCFrame*CFrame.new(x, y, z) newItem:PivotTo(pos*angle) end newItem.Parent = ITEM_LOCATION end This code won't work and is untested but that's the concept. Here are some more resources on the topic: create.roblox.com/docs/reference/engine/datatypes/CFrame#Inverse create.roblox.com/docs/building-and-visuals/studio-modeling/object-world-space create.roblox.com/docs/reference/engine/datatypes/CFrame#ToObjectSpace create.roblox.com/docs/reference/engine/datatypes/CFrame#ToWorldSpace You can also take a look at a video I made on this topic: th-cam.com/video/F413drdadDs/w-d-xo.html
Look for the IntValue 90 or the number in the CFrame in the rotate function and change it to 45 degrees :) assuming you used his plot system. Good luck c You could very much easily alter his code to do this simply. With little coding knowledge at all.
A better way would be to use a Enum key code like R to rotate and to display this as a icon and also use that same icon for mobile players to rotate hope this made sense What I mean is use the same code for the mobile button but change the function and the trigger for mobile inputs
For any object, assuming you want to reconstruct it, you just take the components you want to save and add them into a table. In your case, if you're just needing to save a value of the GUI's visibility, you can actually just save either the Enabled property on the ScreenGui or the Visible property on the frame that contains the UI elements since they are a boolean value.
unless you are storing thousands of parts per object, you should be fine. If you do run into issues relating to the data limit, you will need to look into data compression.
Yes, what I did was equivalent to using math.rad(). The reason I didn't use it was to show exactly what was going on. But yes, you are correct, you can simply use math.rad().
For tycoons what I recommend doing is simply looping through the objects on the tycoon, save the models position using GetPivot() (or by using the primary part position), then save the model name. When the player rejoins, you can use the name to access the model, and use the PivotTo() method to place it on the plot using the saved values.
--Services local players = game:GetService("Players") local dataStoreService = game:GetService("DataStoreService") local dataStore = dataStoreService:GetDataStore ("InstanceSave") -- Variables local keyPrefix = "Player: " local parts = workspace.Parts --Functions local function save(player: Player) local key = keyPrefix .. tostring(player.UserId) local data = {} for i, obj: BasePart in ipairs (parts:GetChildren()) do table.insert(data, { obj.Name, obj.CanCollide, -- Position obj.CFrame.Position.X, obj.CFrame.Position.Y, obj.CFrame.Position.Z, -- Rotation obj.Orientation.X, obj.Orientation.Y, obj.Orientation.Z }) end local success, err repeat success, err = pcall(function() dataStore:UpdateAsync(key, function() return data end) end) task.wait() until success if not success then warn("failed to save data".. tostring(err)) end end local function load(player: Player) local key = keyPrefix .. tostring(player.UserId) local success, err local data repeat success, err = pcall(function() data = dataStore:GetAsync(key) end) until success or not player:FindFirstChild(player.Name) if not data then return end if success then for i, obj in ipairs(data) do local newPart = Instance.new("Part") newPart.Name = obj[1] newPart.CanCollide = obj[2] newPart.CFrame = CFrame.new(obj[3], obj[4], obj[5]) newPart.CFrame *= CFrame.Angles(obj[6]*math.pi/180, obj[7]*math.pi/180, obj[8]*math.pi/180) newPart.Anchored = false newPart.TopSurface = Enum.SurfaceType.SmoothNoOutlines newPart.Parent = workspace end else warn("failed to load data: " .. tostring(err)) end end --Signals players.PlayerAdded:Connect(load) players.PlayerRemoving:Connect(save) game:BindToClose(function() for i, plr: Player in ipairs(players:GetPlayers()) do save(plr) end end)
To save every part within a model, you'd have to use the process shown in this video but on every object within a model. You can use GetDescendants() to run through all the parts in a model, save their components, and then load when needed.
hey man im making a simulator nd the doors work perfectly, and when one player passes trough the door it goes away for the other players too. can you help me fix this please
local players = game:GetService("Players") local dataStoreService = game:GetService("DataStoreService") local dataStore = dataStoreService:GetDataStore("InstanceSave") local keyPrefix = "Player: " local parts = players.player local function save (player: Player) local key = keyPrefix .. tostring(player.UserId) local data = {}
for i, obj: StringValue in ipairs(parts:GetChildren()) do table.insert(data, { obj.Name, obj.Value, }) end
local success, err repeat success, err = pcall(function() dataStore:UpdateAsync(key, function() return data end) end)
task.wait() until success
if not success then warn("Failed to save" .. tostring(err)) end end local function load(player: Player) local key = keyPrefix .. tostring(player.UserId) local success, err local data
repeat success, err = pcall(function() data = dataStore:GetAsync(key) end) until success or not players:FindFirstChild(player.Name)
if not data then return end if success then for i, obj in ipairs(data) do local newPart = Instance.new("StringValue") newPart.Name = obj[1] newPart.Value = obj[2] newPart.Anchored = true newPart.Parent = player end else warn("Failed to load data: " .. tostring(err)) end end players.PlayerAdded:Connect(load) players.PlayerRemoving:Connect(save) game:BindToClose(function() for i, plr: Player in ipairs(players:GetPlayers()) do save(plr) end end)
I hope this video has helped in some way. If you have any questions or problems, join the discord server: discord.gg/xJB2Adu4cr. Another way to reach me for dev support related questions is to @ me in a dev forum post. Thanks for watching, hope it helped!
EVERYTHING ELSE WAS SO CONFUSING, THIS HELPED SO GOD DAMN MUCH. THANK YOU KIND SOUL 😭😭
great tutorial! personally, i used setasync() instead of updateasync() because of updateasync being slower and sending more api requests.
to anyone reading this, keep this in mind!
I've personally never head of updateasync lol
Me too used a long time ago SetAsync... Some players lost they Data. With UpdateAsync no one isn't lost Data
I was really confused on how to save non values to datastores, thank you so much!
I was thinking this would take like 300 lines of code.. you saved my game thank you
ty i used to not know how to do datastore for folder i used to think it was so consufing and i finally did it (lil dif frm urs it was just a plr folder i put there and yea) tysm 👍
oml frigging thank you. ive been searching for this FOR HOURSSSS!!!!
i frigging luv u
words cannot express how much pain and suffering i was in for THESE YEARS
i frigging luv u
i actually use this technique for important objects like a custom block a player made in a game
a great sequal to the placement series
Greatly explained, easy to understand!
Man u are so underrated I am in love with ur tutorials
Thank you so much! This is exactly what i needed for my game!
I recently came up with an idea for a tycoon sort of game and needed this to save what the player bought.
FINNALY THANK YOUU
I’ve been doing this the long way around for too long… 😒 Thank you for the lesson!!
Glad I could help you out!
The tutorial was really useful, thanks alot! Also, a type checking tutorial would be of great help!
You should go more in-depth with the placement system and this and make some form of housing system with a UI and such
This is an incredibly useful video, thanks!
thanks for the awesome tutorial
bro summoned every tycoon / building game owners by this video.
me
I'm a fan of your OCD
thanks im making roblox inside of roblox and im adding a studio
can you implement a saving system into the placement system? it would really be helpful because i'm making a game kind of like mini cities. everything works I just need it to save but I don't know how to do it. if you had time to implement a saving system kind of like this but works with the placement system series you made, it would be awesome. thanks
fr
THANK YOU!
aha, thank you, this is very well explained. I think im missing some context: am i right in thinking that this solution would be useful when making a placement system (of parts)? right now however, the relevant parts are in the datahandler... would i be correct thinking that 1. this is the place a placement system would save parts to? (which then are saved to the datastore when a player leaves) 2. if you wanted parts to not be linked to a player so much as to a server, then the starting signal shouldn't be playeradded but server startup (if that is something that exists)? I have read quite a lot and watched videos on datastores, but not proficient yet, please excuse me if im not getting things right. thank you for your response in advance
Thank you
This was a great tutorial
This works but my statue becomes a plain part and the color isn't saved
why arent you saving the obj's vector3's instead of each single position?
I love these videos
why do you need to put in the x y z seperately? cant we do obj.CFrame.Position instead of obj.CFrame.Position.X obj.CFrame.Position.Y obj.CFrame.Position.Z?
i get error:
DataStoreService: CantStoreValue: Cannot store Array in data store. Data stores can only accept valid UTF-8 characters. API: UpdateAsync, Data Store: SBGObjectsData
HELP! attempt to index nil with UserId
Profile Service 🗿🍷
do how to save humanoid next, for example like "MaxHealth" etc
Make a Value for a players health amount then make a DataStore for the Value then when the player joins the health amount is the same as the value
Does this work with complex models that are rigged with animations
Awesome! Is there away to save gui data. Like if someone wanted to mute music in the game and they go to the settings to turn it off then once they leave it saves it and when they join the music is muted.
You can save a boolean so True or False then retrieve that data when they join and if its True then enable the music, if its False then disable it. (Once player clicks music setting button fire an remote event to change the value in datastore, just make sure the arguments are Boolean so you just pass in True or False when firing.)
help, when saving the data, it says i cannot store array in data store and can only accept valid UTF-8 characters
Convert it to json ,wait I'm late to reply
just use instead of: obj.Color: obj.Color.R
obj.Color.G
obj.Color.B
Wait im so late to reply
how can you save the brickcolor? i've tried many ways but it keeps on putting in the wrong type of color to each part. Could u please help me out? Please respond asap.
may you tell me how do you run it by a gui like save button? if you press the button it will save your parts, also for the load button too and make multiple buttons for other buildings and different stuff
can you also just put obj.CFrame.Position instead of getting all the axis? same with the orientation?
any way to save size too? and color3.FromRGB
IS this possible with gui objects in a tag? Because i want to save the visibility of the gui object, in my case a button and a text label. But how can i achieve that?
Can anyone help me? I tryed this for my gui and it didnt work?
Tyyyy
hey mate! Im a little nooby dev, wanted to ask how to save the position of a model inside a limited position like ex: a restaurant tycoon you place stuff and you save it bt there are dif spots and want them to spawn like you want to
Do you mean saving positions relative to a plot? If so, what you can do is utilize the CFrame library to convert your positions to local space (aka object space). You can use the Inverse() method to convert the CFrame:
for i, item in ipairs(plot.itemHolder:GetChildren()) do
-- Get 'local' positions and rotation
local objCFrame = plotCFrame:Inverse()*item.PrimaryPart.CFrame
local _, angle = objCFrame:ToOrientation()
-- Add values to table
table.insert(data, {
tostring(item),
objCFrame.X,
objCFrame.Y,
objCFrame.Z,
math.round(angle*(180/math.pi))
})
end
That will save the data relative to the plot chosen. To load in, you can reverse the process by simply multiplying the plot CFrame and the objects CFrame to convert back to world coordinates:
for i, item in ipairs(savedData) do
local newItem = items:FindFirstChild(item[1]):Clone()
if newItem then
local x = item[2]
local y = item[3]
local z = item[4]
local yAngle = item[5]*math.pi/180
local angle = CFrame.fromEulerAnglesXYZ(0, yAngle, 0)
local pos = plotCFrame*CFrame.new(x, y, z)
newItem:PivotTo(pos*angle)
end
newItem.Parent = ITEM_LOCATION
end
This code won't work and is untested but that's the concept. Here are some more resources on the topic:
create.roblox.com/docs/reference/engine/datatypes/CFrame#Inverse
create.roblox.com/docs/building-and-visuals/studio-modeling/object-world-space
create.roblox.com/docs/reference/engine/datatypes/CFrame#ToObjectSpace
create.roblox.com/docs/reference/engine/datatypes/CFrame#ToWorldSpace
You can also take a look at a video I made on this topic: th-cam.com/video/F413drdadDs/w-d-xo.html
@@zblox164 you are my god
@@palomarechoncha369 Glad I could help!
What if the part has a script inside?
didn't work : ( like there are error everywhere in the script. I wish i could just copy and paste it so that it maybe don't have the errors
Could you do a part 11 of the placement system tutorial that shows us how to implement horizontal placement?
Look for the IntValue 90 or the number in the CFrame in the rotate function and change it to 45 degrees :) assuming you used his plot system. Good luck c
You could very much easily alter his code to do this simply.
With little coding knowledge at all.
A better way would be to use a Enum key code like R to rotate and to display this as a icon and also use that same icon for mobile players to rotate hope this made sense
What I mean is use the same code for the mobile button but change the function and the trigger for mobile inputs
yo could we see the whole script?
is there any way you could save value's and then load the value in the same numbervalue?
how can i do this but with gui? for example i want my gui to become invisible and when the player rejoins its still invisible?
For any object, assuming you want to reconstruct it, you just take the components you want to save and add them into a table. In your case, if you're just needing to save a value of the GUI's visibility, you can actually just save either the Enabled property on the ScreenGui or the Visible property on the frame that contains the UI elements since they are a boolean value.
I need to get the color(hsv) from a mesh part. How do I get the hue sat and Val?
there is a problem with the first script when ever i typed in "load" "save" it underlined it in red, i don't think the script works any more
It always works, try checking for any mistakes.
hello, how can i save objects with scripts and other stuffs
what if the object has too many parts? a datastore key can only have 4 mb of data.
unless you are storing thousands of parts per object, you should be fine. If you do run into issues relating to the data limit, you will need to look into data compression.
a lot of yapping and code doesnt make sense sometimes.
Hello, i have 1 problem idk if its just for me, but it did not save the size?
you never saved the size, I think it's quite easy to understand how to add size saving
Do you by any chance know how to do this with vehicles?
You can only make create the position and orientation value of vehicles and then save them, if needed you can do more.
12:27, couldn't you just use the math.rad function?
Yes, what I did was equivalent to using math.rad(). The reason I didn't use it was to show exactly what was going on. But yes, you are correct, you can simply use math.rad().
yo bro what should i do if i need to save a lot of folders and models(i creating a tycoon)
cuz i cant write obj.CFrame and etc help me!
For tycoons what I recommend doing is simply looping through the objects on the tycoon, save the models position using GetPivot() (or by using the primary part position), then save the model name. When the player rejoins, you can use the name to access the model, and use the PivotTo() method to place it on the plot using the saved values.
Could you send me the script? Im too lazy to type lol
can you pls publish this script, it would be easyer
--Services
local players = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")
local dataStore = dataStoreService:GetDataStore ("InstanceSave")
-- Variables
local keyPrefix = "Player: "
local parts = workspace.Parts
--Functions
local function save(player: Player)
local key = keyPrefix .. tostring(player.UserId)
local data = {}
for i, obj: BasePart in ipairs (parts:GetChildren()) do
table.insert(data, {
obj.Name,
obj.CanCollide,
-- Position
obj.CFrame.Position.X,
obj.CFrame.Position.Y,
obj.CFrame.Position.Z,
-- Rotation
obj.Orientation.X,
obj.Orientation.Y,
obj.Orientation.Z
})
end
local success, err
repeat
success, err = pcall(function()
dataStore:UpdateAsync(key, function()
return data
end)
end)
task.wait()
until success
if not success then
warn("failed to save data".. tostring(err))
end
end
local function load(player: Player)
local key = keyPrefix .. tostring(player.UserId)
local success, err
local data
repeat
success, err = pcall(function()
data = dataStore:GetAsync(key)
end)
until success or not player:FindFirstChild(player.Name)
if not data then
return
end
if success then
for i, obj in ipairs(data) do
local newPart = Instance.new("Part")
newPart.Name = obj[1]
newPart.CanCollide = obj[2]
newPart.CFrame = CFrame.new(obj[3], obj[4], obj[5])
newPart.CFrame *= CFrame.Angles(obj[6]*math.pi/180, obj[7]*math.pi/180, obj[8]*math.pi/180)
newPart.Anchored = false
newPart.TopSurface = Enum.SurfaceType.SmoothNoOutlines
newPart.Parent = workspace
end
else
warn("failed to load data: " .. tostring(err))
end
end
--Signals
players.PlayerAdded:Connect(load)
players.PlayerRemoving:Connect(save)
game:BindToClose(function()
for i, plr: Player in ipairs(players:GetPlayers()) do
save(plr)
end
end)
Is there any way to save a model? On datastore
To save every part within a model, you'd have to use the process shown in this video but on every object within a model. You can use GetDescendants() to run through all the parts in a model, save their components, and then load when needed.
how do I load them on the same spot of a plot when the player has choosen a plot@@zblox164
-
Can you add copy and paste that would be helpfull
hey man im making a simulator nd the doors work perfectly, and when one player passes trough the door it goes away for the other players too. can you help me fix this please
Can you Pls put the script in the description pls
10:49 what if our data is a number value?
did not work datastores make no sense
local players = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")
local dataStore = dataStoreService:GetDataStore("InstanceSave")
local keyPrefix = "Player: "
local parts = players.player
local function save (player: Player)
local key = keyPrefix .. tostring(player.UserId)
local data = {}
for i, obj: StringValue in ipairs(parts:GetChildren()) do
table.insert(data, {
obj.Name,
obj.Value,
})
end
local success, err
repeat
success, err = pcall(function()
dataStore:UpdateAsync(key, function()
return data
end)
end)
task.wait()
until success
if not success then
warn("Failed to save" .. tostring(err))
end
end
local function load(player: Player)
local key = keyPrefix .. tostring(player.UserId)
local success, err
local data
repeat
success, err = pcall(function()
data = dataStore:GetAsync(key)
end)
until success or not players:FindFirstChild(player.Name)
if not data then return end
if success then
for i, obj in ipairs(data) do
local newPart = Instance.new("StringValue")
newPart.Name = obj[1]
newPart.Value = obj[2]
newPart.Anchored = true
newPart.Parent = player
end
else
warn("Failed to load data: " .. tostring(err))
end
end
players.PlayerAdded:Connect(load)
players.PlayerRemoving:Connect(save)
game:BindToClose(function()
for i, plr: Player in ipairs(players:GetPlayers()) do
save(plr)
end
end)
@@NemoNews2 You're parenting the part to the player which is causing the part to not appear, instead parent it to a folder in workspace.
Just use profile service
team fake
i y
ρгό𝔪σŞm
obj[6]*math.pi/180 could just be math.rad(obj[6])
Yes. The reason I didn't do that was to show exactly what was going on. But yes both are equivalent.