How to save unsupported values in datastore easily

Okay, I know someone already made a tutorial about this, but it wasn’t really clear and this tutorial shows the easiest way of saving values like,

  1. Vector3.new
  2. Cframe
  3. Color3
    and etc.

Now you might easily just SetAsync right? Boom. An error popped up.

Why?

Because datastore can only save UTF-8 characters, which means it only stores strings, numbers and text, which means vector3,cframe is not a UTF-8 character

If you follow the 2 steps, you will be able to save positions, colors, etc.

Step 1 - Converting the unsupported value to a table

Datastores can also save tables, which is basically a lifesaver for me, so I want to save a color3 to the datastore, as said. It will print an error

(That’s only 1 line, pretty easy right?)

game:GetService("DataStoreService"):GetDataStore("Colors"):SetAsync("plr",{R = block.Color3.R, G = block.Color3.G, B = block.Color3.B})

The more arguments, the more arguments you need to add in the table.
basically depending on arguments.

yay no more errors

Step 2 - Reconverting table to the unsupported value

Okay, since you saved it to the datastore successfully, you’re gonna hype to :GetAsync() the color key

But wait… it’s always returns the black color, I wanted white!

That’s because that now you saved it as table, you need to make it color3 again.

Now I want the brick to be white

local retrieveddata = game:GetService("DataStoreService"):GetDataStore("Colors"):GetAsync("plr")
-- i added local because ill not retrieve data 3 times
game.Workspace.brick.Color3 = Color3.new(retrieveddata.R,retrieveddata.G,retrieveddata.B)

Yay, now it’s white!

Now you’re able to load and save vector3, cframes into datastore, ofcourse there are other ways to do it but I think this is the easiest

Bonus : Saving enums + loading them

Okay, you can now save parts to datastore, but what if you wanna save the material too? You can’t do that with tables. And that’s why I made the bonus

So?

Enums can’t also be saved in datastore as it’s not an UTF-8 character too
But you can’t convert it to table either, so we’re gonna convert it to string instead

This function returns the enum as a string.
It’s also 1 line
So , saving the enum.

game:GetService("DataStoreService"):GetDataStore("material"):SetAsync("ilikeplastic",part.Material.Name)

Now for the loading

part.Material = Enum.Material[game:GetService("DataStoreService"):GetDataStore("material"):GetAsync("ilikeplastic")]

cool, now you can save all kinds of unsupported values completely

Saving the value and loading them without using dictionaries

This section is suggested by @jelliedbanana1

This is for people who worries about the character limit. If you’re not worrying ab it or is just saving with part limit etc this shouldn’t matter unless it’s huge. The datastore character limit is like 2 MB which is a good thing, it’s huge, however what if you’re making a saving huge buildings system, like what if the map is too huge for it to be saved with dictionaries?

Ok now this method does not do a big change comparing to the dictionaries but hey, it does some free space.

So let’s make it into a table.

game:GetService("DataStoreService"):GetDataStore("Colors"):SetAsync("plr",{block.Color3.R,block.Color3.G,block.Color3.B})

You might see no difference right? We removed the spaces and the R =, G = , B = .

Now for the loading, we have two ways.

  1. Table.unpack
local retrieveddata = game:GetService("DataStoreService"):GetDataStore("Colors"):GetAsync("plr")
game.Workspace.brick.Color3 = Color3.new(table.unpack(retrieveddata))
  1. I have no idea what to name this
local retrieveddata = game:GetService("DataStoreService"):GetDataStore("Colors"):GetAsync("plr")
game.Workspace.brick.Color3 = Color3.new(retrieved data[1],retrieveddata[2],retrieveddata[3])

Although I wouldn’t recommend the 2nd way for saving maps, I recommend table.unpack instead.

Sorry for not being indepth as it already is obvious on what it does, I am just lazy

Yeah, that was quick and an easy tutorial, you can send feedback s

33 Likes

Thanks for the information, I actually didn’t think about using tables for things like that! :grinning_face_with_smiling_eyes:

2 Likes

Why is there no recognition???

2 Likes

this is so easily than i thought. Thanks for making this​:+1::+1:

3 Likes

I’m also creating a bonus step. Saving enums. It will just take a while to write it

Edit : I’m done! You can read the bonus step now

Wouldn’t this work?

partInfo = {
     Size = tostring(part.Size),
     Position = tostring(part.Position)
     Color = tostring(part.Color3)
     Material = part.Material.Name
}

it would be harder to load, just convert it to table.

and for the enum, you can totype it

“text” and “string” are the same thing. Also, I dunno why you needed to mention UTF-8 here, UTF-8 is a data storage format, and technically, you can store anything as UTF-8, as long as you have a way to read from it.

Also lowkey I feel like you stole this part from some other post…

3 Likes

OK, I see your point here, but why are you using a function?
why not just doing:

partInfo = {
Size = {part.Size.X, part.Size.Y, part.Size.Z},
Position = {part.Position .X, part.Position .Y, part.Position .Z},
Color = {part.Color3.R , part.Color3.G, part.Color3.B},
Material = part.Material.Name
}

It’s basically the same and makes the script look cleaner, not with so many small functions that look annoying

Don’t get me wrong, it’s a great idea. I just disagree in using functions for everything

its just easier with them. it makes it look less complex, however your not wrong, you can just do it without functions

do

Material = totype(part.Material.Name)
1 Like

which one?

to make them understand that you cant save parts with

Setasync(part)

thats why its mentioned

Dictionaries take up more space than a usual table, consider doing something like this instead.

function makeSaveableColor3(color3)
	return {color3.R, color3.G, color3.B};
end

function makeColor3FromSaved(savedColor3)
	return Color3.new(table.unpack(savedColor3));
end
1 Like

ook thanks for suggesting ill use that next time
(lucky that i didnt use [“s”] for dictionaries as they take up much more space)

1 Like

I have a partsaver that saves parts based off of their properties, all you have to do is pcall through all 400+ properties to see which it has and store the property name that succeeded as well as the value. This way you can save pretty much anything and everything with no errors. Also I would avoid using a table for a datastore because it takes up more characters, if you are saving high volumes of data that can slow things down.

Instead do table.concat() and use string.split() to seperate it out again to save usage.

Also to get the properties back to be usable like as vector3 e.c.t, i just pcall when im setting the property to see if it it is the correct type.

This one. The description of UTF-8 seems pretty similar to me.

oh yeah but i still needed to mention it. dosent change the fact that its not good to put it there

why should i remove that to make people still think that

Setasync(part)

can save part.

actually, i think thats the good time to use dictionaries because pcalls arent efficient at all.
pcalls should only be used for web calls and datastores.

i might be wrong tho.

local MyData = game:GetService("DataStoreService"):GetDataStore("MyData")
local Players = game:GetService("Players")

local Part = workspace.Part

Players.PlayerRemoving:Connect(function(player)

    local DataTable = {
    X = Part.Position.X;
    Y = Part.Position.Y;
    Z = Part.Position.Z
}
     MyData:UpdateAsync(player.UserId, function() return DataTable end)
end)

Players.PlayerAdded:Connect(function(player)
   local SavedData = MyData:GetAsync(player.UserId)

   if SavedData ~= nil then
       Part.Position = Vector3.new(SavedData.X, SavedData.Y, SavedData.Z)
  else
       print("Data is nil")
   end
end)

This is an example of how I save position, color, etc. And works really well.

But your idea is great too.

This looks like my tutorial mentioned by some player here

Just a correction:


UTF-8 means tables too, you did not include that

1 Like

Basically, RDBMS is the format used by huge companies like Roblox, UTF-8 is not a format

Note that, UTF-8 means a non-instance, or a value which is not an object
Its not a format for any data store, and 90% of the games of roblox which we see are objects

UI, blocks and scripts all of these are instances
Now you cannot save these directly, they are instances, not non-instances

And you need a primary key to save a data in a table of DataStore in Roblox

So, you need to make them into data which can be saved in data stores, which is a non-instance or UTF-8 characters

2 Likes