Of course, there are ways to optimize based on your specific use case. His tutorial was written with a more general audience in mind.
Thank you so much for this! I am quite new at scripting, so this is extremely useful for me! I can’t wait for new tutorials by you, keep it up!
This is a nice tutorial, honestly. It shows one of the huge possibilities of programming, and in programming, anything is possible.
Seriously though, this is a really great explanation. I’ve been recently wondering how to save parts and all. Before seeing this tutorial, I felt like it would be an advanced-level process and set of huge complications, but now that I’ve seen this tutorial, it’s as simple as storing properties in tables, encoding + decoding it, and using the serialized properties to create a new Instance with all of the properties.
Good job on the explanation!
Pretty sure SpecialMesh
es can be changed during runtime, so if you would REALLY need to keep the same mesh + texture when serializing / deserializing, you could probably use those. But unfortunately I don’t think materials can be applied on a part with SpecialMeshes. BrickColor property also won’t work on SpecialMesh
es, as that Instance has a VertexColor property, so BrickColor cannot override it.
More importantly, SpecialMeshes do not affect collision geometry so even if you could bring it back visually, it wouldn’t actually be functionally the same as the original serialized mesh.
What was the point of using the HTTP service? Doesn’t roblox already convert tables to JSON, and what makes saving strings better than tables? I’ve done this multiple times before without using the HTTP service and have not run into any issues.
Did you read the OP? The tutorial explains serialization. In this case an instance is serialized into a table since instances can’t be saved to data stores. A table can indeed be saved in a data store. Roblox indeed JSON-encodes the values to save. Which is also why you shouldn’t do this yourself as you could take up to over 2x the space.
I don’t understand the point you are trying to make, Did he use the Encode function on the instance itself?
The HTTPService contains the JSONEncode() function, for viewing data when it’s in serialized format. It’s not necessary for actually serializing the data but for debugging it’s incredibly useful for seeing how the computer has laid out your table. print(table) will only print the memory pointer, so you need to encode it as text to view it’s layout and contents.
The reason the encoding function is inside the HTTP service is because usually you need it when interacting with web API’s. In this case, we’re only using it for debugging, not actually sending data across the net.
I know that still not answering my question.
Oh I think I see what you mean now that I read it again. The reason why strings are better is because it is required to send the data to a custom datastore. If you’re using the default roblox data store then it won’t be a problem since this is called automatically, but if you’re using mongoose or google spreadsheets or something (I wouldn’t recommend using spreadsheets as a datastore) then you’re going to need this in string format to send it over properly. Was this what you were asking?
Really sorry for the long wait and the late respone.
tl;dr, this is a redundancy of my part, you don’t actually need to :JSONEncode()
the dictionary, roblox does it anyways internally, simple dictionaries that don’t contain userdata (Vector3
s, CFrame
s, instance ect.) can be saved ay okay. People usually get a UTF-8 error when they try to save a userdata, and end up :JSONEncode()
ing the thing which won’t work out, it just ends up replacing the userdata with null
, and loading the data back will just cause trouble. I will change this! Thanks.
This is amazing, I don’t see myself as being that good at scripting, but you explained it very well.
I was able to modify it to save when the player leaves and load when they press a gui button.
Thank you!
[SOLVED!]
I am getting an error. In the function InitProps(objects).
The error is: invalid argument #1 to ‘pairs’ (table expected, got nil).
I am using datastore2 instead and Im hoping I did it right. Would be able to help if I give more info?
solution: starmaq: Like you said, it’s calling Serialize()
sometimes but ends up failing at a certain point. This is because at some point the loop will loop through an obj
that doesn’t have the properties for his class inside of the properties
table. Check which object that is, and add the properties of it that you wanna save in the form of strings! Thanks for the video as well, helped me understand your problem.
Can you please give which line gave the errors? Because there are 2 possibilities. The problem could also just be that you didn’t pass a table to Encode
which calls InitProp
with that table, in which case revise your code first please.
Absolutely. Here is the playerData script I have that contains the reference to the module script serialize:
--required vars
local datastore2 = require(game.ServerScriptService:WaitForChild("DataStore2")) --1936396537 game.ServerScriptService:WaitForChild("DataStore2")
local serialize = require(game.ServerScriptService:WaitForChild("serialize"))
--default vars
local players = game:GetService("Players")
local defaultFunds = 1000
--DONT FORGET:: COMBINE!
datastore2.Combine("playerData", "Funds", "parts")
game.Players.PlayerAdded:Connect(function(player)
--datastore vars
local fundsData = datastore2("Funds", player)
local partsData = datastore2("parts", player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local funds = Instance.new("IntValue")
funds.Name = "Funds"
funds.Value = fundsData:Get(defaultFunds)
funds.Parent = leaderstats
--callbacks
fundsData:OnUpdate(function(newValueFunds)
funds.Value = newValueFunds
local fundstxt = player:WaitForChild("PlayerGui"):WaitForChild("ScreenGui").playerFunds
fundstxt.Text = player:WaitForChild("leaderstats").Funds.Value
end)
--add a parts folder to the player in case of store purchases
local partsFolder = Instance.new("Folder")
partsFolder.Parent = player
partsFolder.Name = "Parts"
----LOADING PARTS FOR EACH PLAYER
--might put this somewhere else, stand by
--SAVING PARTS FOR EACH PLAYER
--current saving action is done by clicking a basepart(being tested)
workspace.workArea.Parts.ChildAdded:Connect(function()
wait(1)
for _, area in pairs(game.Workspace:GetChildren()) do
if area.Name == "workArea" then
if area.ownerShip.Value == player.Name then
local parts = area:FindFirstChild("Parts")
if partsData ~= nil then
local pArray = serialize.Encode(area.Parts:GetChildren())
partsData:Set(pArray)
end
end
end
end
end)
end)
game.Players.PlayerRemoving:Connect(function(player)
--NOTHING TO PUT HERE JUST YET
end)
```lua
AND in the serialize module this is the line with the error:
```lua
function InitProps(objects)
local tableToSave = {}
for _, obj in pairs(objects) do
local class = obj.ClassName
local t = tableToSave[class]
if not(t) then
tableToSave[class] = {}
t = tableToSave[class]
end
local add = {}
*for _, prop in pairs(properties[obj.ClassName]) do* --errors here
add[prop] = Serialize(obj[prop])
end
local children = obj:GetChildren()
if #children > 0 then
add["Children"] = InitProps(children)
end
table.insert(t, add)
end
print("00000000")
return tableToSave
end
```lua
NOTE: I have tried printing tables that are passed and messing around with the datastore2:Set() parameters for 2 days so far. Each one of them give the error.
What is interesting is, I can print properties([obj.ClassName]) and it actually prints the objects and the properties I have assigned. The error comes right after that.
So, the module.Serialize function works! I am returning (r) just fine for the properties. Thats why I am confused it errors lol.
So, as long as I have that error, since it is not a warning, I cannot go further yet.
I am betting it is something to do with the passing of the arguments as you mentioned.
I am not assigning a default to the partsData, but I am assigning a default to the fundsData.
I am testing that now. I have read that could cause issues by not having a defualt.
Thats where I am :P Thank you for the help and no rush ok? I appreciate all the time for sure!
I am posting a video of it also because videos help me A LOT! So, hopefully we can see something
Thanks again!
Like you said, it’s calling Serialize()
sometimes but ends up failing at a certain point. This is because at some point the loop will loop through an obj
that doesn’t have the properties for his class inside of the properties
table. Check which object that is, and add the properties of it that you wanna save in the form of strings! Thanks for the video as well, helped me understand your problem.
You are more than welcome and Im glad you see the same as I presumed I will add at least one property of each child into the properties array and see if it works by at least looping through and finishing.
Will update soon and mark your answer a solution if all good Im assuming the same, that everything will work once I do that. Wish me luck!
SOLVED I have the properties set like this if say the part has these classes as children.
lua
local properties = {
Part = {“Name”, “BrickColor”},
ClickDetector = {“Name”},
IntValue = {“Name”, “Value”},
StringValue = {“Name”, “Value”},
Script = {“Name”}
}
Thank you for the insight and help again! This is a great effort and appreciated. Do you want anything for the time you put into making this?
Now, I just have to figure out how to remove items and that’ll be easier I hope lol. Good to go and hope this helps anyone who might need to change the properties for their situation!