Should we instantiate datastore variables into physical objects?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    As my current setup for datastore is to convert a nested folder structure to a dictionary before saving it.
    This includes retreiving classnames and values so that I can replicate the dictionary to instances. What I am curious about is if the standard way for handling PlayerData (manipulate/add/remove/increment). Do you guys do it directly on the dictionary.

  2. What is the issue? Include screenshots / videos if possible!
    For me, I have always instantiated variables into a folder in ServerScriptService.

Pros:
The main reasons I’ve done this is the ability to manipulate the variables directly in studio for testing purposes. It also lets be quickly add and remove instances.

Cons:
Adds another intermediate conversion whenever you have to save and load from datastore. Basically you have to convert back between a nested folder and an array which is a very tedious process

My main question is how developers organize their PlayerData. I have seen people use frameworks such as ProfileService/Datastore2 but afaik you still have to prepare the PlayerData that you want to save and load.

So the way I have been preparing my data is to make a recursive function that converts all metadata from the nested folder and save it into a dictionary. When loading it, I use the metadata to create the correct classes and adds the value for it. What are you guys doing?

1 Like

Hm, well for the game I’m creating when the player joins I create a cache for them, and throughout the game edit the cache then when something vital needs to be saved or the player leaves thats when I saved, but I’m also create actual objects that reflect the data that is loaded in, I’m mainly doing this so that I dont have to use remotes to retrieve data which will have latency, so having the client able to read the data directly from the client is just faster

For when the player leaves since I have the cache of the player’s data, I just saved the cache, I dont really need to convert those folders with values in them into a dictionary because, I can just use the cache I created when they first joind the game, so basically I use a dictionary and also actual objects that reflect that dictionary

2 Likes

Not necessarily, if you design your system so that there’s just one system that deals with it in the background and all other systems interact with saved data through a common interface it provides. If you post some example code showing what you find tedious about it, I can suggest ways of automating it away.

How have you tested that? It’s a result that I find surprising, as the data has to be replicated to clients no matter what. Are you sure it’s not just an effect of replicating the data as soon as it changes instead of the client asking for a value and waiting for a round trip before getting it? That could be avoided without Instances to represent the data as well.

1 Like

Well sending asking the server for something and then waiting for a response back is always going to be slower than just getting that piece of data directly from the client

For example I had this main menu system which wouldn’t allow players to start the game if there was a match in progress so on the client I would invoke the server and ask if there was a round in progress, THEN if there wasn’t I would allow the player to enter the game, on studio it was barely noticable because well in studio were running on our own local server but in game, the latency was really apparent and I was in a server by myself and at like 50-60ms, so then I went back and made the round in progress value an boolValue that I would change on the server and the client would be able to see, and I made the client read it directly and the latency was gone and it felt so good

So maybe in niche cases it’s more apparent but I think developers should try to use roblox’s built in replication as much as possible

Right, asking the server and waiting for a response takes 1 round trip, like this:

mermaid-diagram-2023-07-24-215423

Here’s what I was describing though (server on the left this time, don’t know how to prevent Mermaid from doing that):

mermaid-diagram-2023-07-24-220043

When the client needs to do something depending on the round-in-progress state, it just uses whatever it last heard from the server so the menu can do it’s thing without waiting for a response to come over the network. I believe this is how ValueBase objects work, and you can write your scripts to work like that as well. I’ve made the arrows point from the client to the client to represent it just looking the value up in a cache, i.e. a dictionary of whatever the server last sent.

To be clear, only horizontal arrows take any appreciable time in these specific diagrams.

1 Like

I think the tedious part is trying to future proof it which probably isn’t a good idea. I am trying to consider nested objects and ways to save their metadata. Currently I am using recursion to reach each value. Main Scripts imports the DataStore module which only has 2 calls (save and load). In the background it converts between instance and dictionary. So far I am uncertain if this is a good way of doing it. There are some possible overhead with creating instances and destroying them.

The most thing I am worried about is that the SaveData method writes to an empty dictionary. In other words. It has to start empty and populate the data every time it saves, which only occurs when the player is leaving.


-- Inside Module SaveFunction
SaveTable = {}
-- iterates through the whole folder structure in recursive manner
-- adding meta_data such as their names and possible values they have
module:Convert_to_dict() 
-- Proceed to save table with datastore

Now I have the option of updating the table during the gameplay. This way I don’t need to recreate the dictionary for each player on leave. Do you think that would possibly be a better idea? As I am experiencing now, the game lags for a bit when the player leaves to save all the data.

Here is a small diagram of how it is supposed to work

1 Like

Reading a few 10s or even 100s of ValueBase objects into a dict shouldn’t take any noticeable time IMO. How are you testing this? Does the leaving player experience the lag, or do all other players? How many ValueBase objects are we talking about?

Amortizing the performance hit like this is an optimization that would work, but in this case I don’t think it’s appropriate. This is because of what I said before: it shouldn’t take any appreciable time in the first place, so writing slightly more performant code that adds a bunch of complexity is not worth it. On top of that, instead of two lag spikes at the start and end of each player’s experience (that shouldn’t be noticeable, but w/e) you now have a bit more code that runs every time the player’s saved state changes, eating up a bit of your performance budget that could be used for other things. Again, not a huge deal because of what you’re dealing with but I still think it’s the wrong call. For other problems this type of optimization can be good tho.

Actually, it might not just be when a player joins and leaves. You might want periodic autosaves and if you for some reason can’t prevent saving from causing a lag spike, having it be in the middle of game play would actually matter for once.

If you want I can take a look at your Convert_to_dict and vice-versa functions to see if there are any obvious performance problems that might be causing the lag spikes you talk about.

1 Like