REFERENCING THE QUOTED REPLY. There may always be a better solution, but HttpService
is the easiest one to my knowledge.
To fix this, you can implement the concept of Serialization / Deserialization. This block of code (courtesy of @starmaq via the ‘How to save parts, and the idea of Serialization’ Devforum post) can convert incompatible datatypes into compatible datatypes. You can use this concept while iterating through each piece of information stored in your tables when you want to send them between the clients and the server. Really recommend you skim through the entire post though, as it gives you a lot of useful information.
local function Serialize(prop) --prop will be the property's value type
local type = typeof(prop) --the type of the value
local r --the returned value afterwards
if type == "BrickColor" then --if it's a brickcolor
r = tostring(prop)
elseif type == "CFrame" then --if it's a cframe
r = {pos = Serialize(prop.Position), rX = Serialize(prop.rightVector), rY = Serialize(prop.upVector), rZ = Serialize(-prop.lookVector)}
elseif type == "Vector3" then --if it was a vector3, this would apply for .Position or .Size property
r = {X = prop.X, Y = prop.Y, Z = prop.Z}
elseif type == "Color3" then --color3
r = {Color3.toHSV(prop)}
elseif type == "EnumItem" then --or an enum, like .Material or .Face property
r = {string.split(tostring(prop), ".")[2], string.split(tostring(prop), ".")[3]}
else --if it's a normal property, like a string or a number, return it
r = prop
end
return r
end
local function Deserialize(prop, value)
local r --this will be the returned deserialized property
if prop == "Position" or prop == "Size" then
r = Vector3.new(value.X, value.Y, value.Z)
elseif prop == "CFrame" then
r = CFrame.fromMatrix(Deserialize("Position", value.pos), Deserialize("Position", value.rX), Deserialize("Position", value.rY), Deserialize("Position", value.rZ))
elseif prop == "BrickColor" then
r = BrickColor.new(value)
elseif prop == "Color" or prop == "Color3" then
r = Color3.fromHSV(unpack(value))
elseif prop == "Material" or prop == "Face" or prop == "Shape" then --you probably have to fill this one depending on the properties you're saving!
r = Enum[value[1]][value[2]]
else
r = value --it gets here if the property
end
return r --return it
end
If you are to use these functions, all I’d recommend is that you put them in a module script that you can reference across multiple scripts, as you may find yourself needing them for more than one piece of your game.
TLDR: user data isn’t really handled well with JSON encoding and you need to convert these pieces of information into encodable data
EDIT: simple wording changes