Currently, to display data to be readable by both client and server, I create a folder in ReplicatedStorage which contains Folders and Values, like so:
This method is obviously simple to setup and use, however I’d finally like to move over to a system more efficient and lighter using modules.
As data within modules does not replicate between server and client (unlike Value instances) I’ll have to transfer the data from the server to client via Remote Events. What is the best way to do this though?
I have two ideas at the moment:
When a stat is changed, fire off the change information to the appropriate players. My worry here is that this could be happening many times a second, especially in a server with lots of players, causing the remote event(s) to throttle.
Set up a loop that repeats every second. Every cycle, check for values which have changed within the time period, then send only the data which has changed to only the appropriate players.
I was wondering, is there an alternative approach to make this method more efficient?
Your first idea is the best way to handle most player data. Some data might get input to be updated often, but not necessarily has to be - you have to apply value update throttling where necessary. Roblox gives you a budget of max 60 KB/s data sent to each individual player and it’s plenty for random data updates. Streamable data updates like player look directions, positions, etc. have to be tested personally. Within a Roblox game you can see your network stats by pressing Shift+F3
What I do is, whenever a client/player needs information from the server, I send an InvokeServer request and then send back the data which is required.
I would also reccomend using _G to store the Player data in tables rather than actual objects.
I’d recommend you avoid using Value objects like this, and I would question whether it is actually simple to setup and use. How would you pass a table from the server to a client? Value objects only work for certain data types, so you may end up having to make exceptions to your system which is messy and undesirable. EchoReaper outlines some related concerns here in the second part of his reply.
The preferable alternative is to maintain a table of players’ data on the server. Transferring this data is done using RemoteEvents/RemoteFunctions. As for the ‘method’ of transferring data (when to do it, and which data to send), you should figure out what the client needs to know and when, and tailor your method of updating to the nature of data it concerns. For example:
When a Client connects, a common practice is to have the Client request its loaded data from the server - typically this comprises all of their session data (e.g. inventory, coins, etc.).
When a Client gains some coins, it makes sense to build into your AwardPoints function some code that pings the client with their updated coin balance because it is likely coin balance is permanently displayed on-screen;
When a Client gains an inventory item (different to coins as inventory generally not permanently displayed), you might consider several different approaches:
Naive approach: ping client with the (whole) updated inventory table;
Lazy-load approach: send nothing immediately - client requests their updated inventory when they open their inventory UI;
Event approach: ping client to say ‘you got item X’ - they can add it to their inventory data locally.
This doesn’t cover all the situations you might encounter, but hopefully it gives you some insight into best practices.
In my data systems I just create a dictionary of Players’ data and add/remove from it when needed. I would definitely recommend it compared to using Values simply because it is more concise; you don’t need to create any objects or index twice instead of once to get an actual value.
To be honest, the system I am running right now is that when there is any change, a player’s entire data table gets sent to their client with a RemoteEvent. You could try that, but you might encounter an issue like you wrote about with throttling.
That being said, the only solutions to throttling I can think of at the moment is just splitting up your data into multiple events. When the core stats change (age, age time, cash, etc.) you fire a ‘stats’ RemoteEvent, and when your arrays/dictionaries change, you fire a relevant remote event (like a ‘friends’ one for friends and friend requests).