Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

Work-arounds to save a CFrame into a DataStore??

Asked by
Xduel 211 Moderation Voter
7 years ago
Edited 7 years ago

I currently have a script that is supposed to save the CFrame of a model into a DataStore.

At first I figured I could just use :GetModelCFrame() and save that as a value, but after testing and further research, I've figured out you can't save CFrames into a DataStore.

It has to save the Rotation and Position of the Model into a DataStore, but it can't be a CFrame. Not sure how I could work around this, and don't really know where to start. Could really use another thought on here. Thanks!

0
Next time search google first; this has been answered before. cabbler 1942 — 7y

1 answer

Log in to vote
5
Answered by 7 years ago
Edited 7 years ago

Serializing


The solution to transmitting or compacting any incompatible data is known as serialization. Likewise, the receiving or unpacking of any serialized data is known as deserialization.


For a better idea, say I want to drop a 5x5x5 ice cube into a 1x1 square hole. I can serialize the ice cube by converting it back into it's liquid form (water), and the water will easily flow right through the 1x1 opening. I can then deserialize the water by freezing it back into a 5x5x5 ice cube once it's on the other side, and I've successfully transmitted data that we otherwise wouldn't be able to!

Applying this to ROBLOX and data store

Every instance of CFrame comes in the data type of userdata. It's important to know that when saving data to data store, it's not as simple as just passing it from point A to point B as you would arguments to a function. These incompatible data types need to be properly encoded before being transmitted.

The only data types that don't need to be encoded before they're sent off to ROBLOX's backend, are strings and integers. Now you're probably thinking, "then why are we able to save tables?". This is because ROBLOX actually encodes the table (to a string value) before it's sent off to their data storage. The encoding format they use to do this is known as JavaScript Object Notation (or JSON), which is quite popular. I'll leave you some more information on JSON here if you're interested.

Solution

Alright, hopefully I didn't bore you too much with all that information. On to the fun part, implementing all of this in code. Now just like I said before, the only data that can actually be saved to data store are strings and integers. So how can we save other data types...? By converting them into strings or integers!

Sometimes serializing data can be a real pain, because it may not have many descriptive attributes. Luckily for us, encoding and decoding a CFrame is very easy! We can utilize a function called components which we can call as a method on a CFrame instance that returns all the information about the CFrame as it's unpacked matrix! Here's an example.

local function encodeCFrame(cf) 
    -- Return the tuple of numbers components() returns, and pack it into a table.
    return {cf:components()}
end

This now converts the CFrame data into a table, which is automatically encoded by ROBLOX. You'll now be able to save this CFrame value once it's been passed through this function. All that's left is decoding, which is equally simplistic!

local function decodeCFrame(cf) 
    -- Return a new CFrame, with the exact same orientation as the one we saved.
    return CFrame.new(unpack(cf))
end

Combining this together to create a save and load system, would yield something like this:

local DataStore = game:GetService("DataStoreService")
local storage = DataStore:GetDataStore("Test")

local function encodeCFrame(cf) 
    return {cf:components()}
end

local function decodeCFrame(cf) 
    return CFrame.new(unpack(cf))
end

local myCFrame = CFrame.new(1, 5, 1) * CFrame.Angles(0, math.pi, 0)
storage:SetAsync("CFrame", encodeCFrame(myCFrame))
print(storage:GetAsync("CFrame")) -- > Our exact CFrame!

Hope I didn't go overboard on explanation, but there it is. If you have any questions, feel free to write a comment and let me know.

Edit for future readers

It came to my attention that I forgot to mention booleans! Boolean values (like strings, and integers), also do not need to be encoded to be saved directly to data store. The same goes for nil values as well, although it's (still) equivalent to nothing.

1
Holy cow! Thank you SO much, I was honestly not expecting such a well worded and thought out answer!! I would like to ask one more thing, and I'm hoping it's something you'd know. One of my concerns with saving full-length CFrames is exceeding the DataStore limit of 260,000 characters. To account for this, I want to have the ability to check and see how much data is being used by the DataStore to Xduel 211 — 7y
0
...not exceed the limit. For that,would converting the DataStore table into JSON and getting the length of it be an accurate representation of how much data is being used? Xduel 211 — 7y
0
Exactly right. You can encode Lua tables to JSON yourself with ROBLOX's JSONEncode function (member of HTTP service), and getting the length of that string will show you how many bytes (characters) it's using. ScriptGuider 5640 — 7y
0
However, I wouldn't worry about exceeding the data limit in this situation unless you're saving a massive table of encoded CFrame values. ScriptGuider 5640 — 7y
Ad

Answer this question