Hello! I want to know how many datastores can a game have because the dev hub does not say anything about it. In other words, it is how many local DataStore = game:GetService("DataStoreService"):GetDataStore("Datas") can I have because my I have lots of inventory-systems in my game and there were lots of dataloss. I want to make it kinda like this instead:
--when player leaves
game:GetService("DataStoreService"):GetDataStore(tostring(player.UserId)):SetAsync(PlayerDatas)
So every single player has his/her own datastore and it will be better. But there might be a limit so I want to know how many local DataStore = game:GetService("DataStoreService"):GetDataStore("Datas") can a game have. Please answer me if you know! Thank you!
Datastore keys are technically infinite to my knowledge though I’d like to correct how you are saving your data as it’s not right. Hopefully this helps.
local DataStoreService = game:GetService("DataStoreService") --Define the service
local Datastore = DataStoreService:GetDataStore("PlayerData") --Create our datastore
Datastore:GetAsync(Player.UserId, Data) --Load data from player id
Datastore:SetAsync(Player.UserId, Data) --Save data to player id
I can make a full datastore example if you like.
You don’t create a new datastore for each player. You create a single datastore then save each player to their own key.
Yes, that is how it is working right now. But there are datalosses for my inventory system. Maybe it’s my own code that is the problem because other data like coins, gems, etc. never had dataloss. Can you help? Here is code:
–In the player added function
wait(1)
local SpellInv = nil
for i = 1, 10 do
if SpellInv == nil then
invData:GetAsync(userId.."SpellInv")
end
wait()
end
if SpellInv then
coroutine.resume(coroutine.create(function()
for i, spellName in pairs (SpellInv)do
local stringValue = Instance.new("StringValue")
stringValue.Name = spellName
stringValue.Parent = player.SpellInventory
wait(0.1)
end
end))
else
print("NO SPELL INV")
end
And the saving part:
local inventory = {}
for i, v in pairs (player.SpellInventory:GetChildren()) do
table.insert(inventory,v.Name)
end
local success, errorMessage = pcall(function()
invData:SetAsync(userId.."SpellInv",inventory)
end)
if not success then
print(errorMessage)
saveData(player)
end
I’ll try my best to create my own datastore for your system. Pretty sure your losing data when your requesting it. I’ll reply once done and I’ll make to comment it for you to understand.
--Setup
local DataStoreService = game:GetService("DataStoreService") --Define the service
local Datastore = DataStoreService:GetDataStore("Spells") --Create a datastore for spells
local DataCache = {} --Create a cache for our data so we can use it later
--Loading data when a player joins
game.Players.PlayerAdded:Connect(function(Player) --Player joins the game
local Success, Data = pcall(function() --Run a pcall to catch errors
return Datastore:GetAsync(Player.UserId) --Get the players data
end)
if Success then --Check if getting the data worked
--If it did work lets continue and check if the player has data
if not Data then --Check if they are a new player
--New player so let's create them data
--I recommend switching to tables instead in string values cause you can add more things in one datastore like so:
Data = {
Coins = 100,
Level = 1,
Spells = {"Fire", "Water"}
}
end
DataCache[Player.Name] = Data --Asign their data to the cache
else
--If it didn't work you could have another attempt if you set it up that way
--For now we are just going to kick the player
Player:Kick("Error loading data")
end
end)
--Now for example we want to update the players data we can do:
DataCache[Player.Name].Coins = 1000 --Set their coins to 1000
--Or we want to add a spell we can do:
table.insert(DataCache[Player.Name].Spells, "Ice") --Add ice spell to spells.
--Or we can read each spell
for i, Spell in pairs(DataCache[Player.Name].Spells) do
print(Spell) --Fire
end
--Saving data now
game.Players.PlayerRemoving:Connect(function(Player) --Player leaving the game
Datastore:SetAsync(Player.UserId, DataCache[Player.Name]) --Save their data
DataCache[Player.Name] = nil --Remove their data from the cache as it's no longer needed
end)
I can see the logic, and i think the key difference is that i have a folder inside the player instance, containing their spells because i need to access their inventory from other scripts and local scripts too. Is there a way you can convert the code into using a folder instance in the player? Thank you!
I’ve provided you the to a datastore system so you should be able tweak it and switch to using a folder with string values but it’s generally a bad practice or bad way to doing things. You should really look into setting up Remote Functions to request the data when the client needs it. if you really really, really wan’t to use StringValues then I recommend the new Attributes instead.
For example:
Server
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
Remotes.RequestData.OnServerInvoke = function(Player)
return DataCache[Player.Name]
end
Client
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local Data = Remotes.RequestData:InvokeServer()
print(Data.Spells) --Prints spells
Ok. But is there a way to save dictionary into object? Because there isn’t a DictionaryValue object so how do i do this? I won’t place it as descendant of the player tho
EDIT:
Oh yes that might be a way. I will try it out thanks
EDIT 2:
How do i use bindable functions for this as well because i sometimes need it from another server script
I’m trying to tell you that saving the data physically with the use of Values or Attributes isn’t a very good way. The one environment I can see using physical representations of values would be like leaderstats with coins for example.
EDIT 2 Reply:
I’ve actually personally never used bindable functions so I have no say on them, sorry.
There’s a dedicated section in the documentation page for DataStores named “Limits” which goes over the various limitations imposed on DataStores, such as the key length, value length etc.
If I use the way @alphajpeg suggested, it would reach the datastore limit pretty fast. So I was thinking of making one datastore for each player so they can’t reach the 4 million characters limit. Is it good performance?
4 million characters is way more data then you should need to store per player, almost ever. If you find yourself reaching that limit, you should reconsider how you save data.
Edit (11/12): The only exception is unlimited builds which can take up infinite space, in which case it might be feasible to store them separately. If you do not have this and find yourself reaching the limit, there are likely better ways for you to store your data. See example below.
For example, if you were storing crates inventory,
{
{
Type = "Legendary",
},
{
Type = "Legendary",
},
{
Type = "Legendary",
},
{
Type = "Legendary",
},
}
is less efficient than:
{
Legendary = 4
}
Even better, you can use ids instead of a whole string
{
[1] = 4
}
The point is: being mindful of how you store data is just as important as what you store.
Um… i think u misunderstood. What I mean is, each datastore has a limit of 4 million characters. So, if I do what @alphajpeg suggested, which is storing everything in one datastore, it will be filled pretty quick. But my idea is to make a datastore for EACH player, so its kinda like this
So every player has his own datastore. The point is so that the limit of 4 mil characters would never be reached. I don’t want dataloss so I think this might be a good way. It is quite impossible for a single player’s data to reach 4 mil characters so it will never fill. But, if I use @alphajpeg way, which is storing every player’s every data into one datastore, it will probably fill up really quick. But creating tons of datastore for each player might also not be good. So what should I do?
Each key within a datastore has a limit of 4 million characters. (Source)
There is no limit of data storage related to datastore or scope, only the key. (There is a limit on scope and datastore name length, but that doesn’t affect data storage)
Since GetDataStore is ratelimited, you can save yourself the hassle by storing all of your data in one datastore, and using a player’s UserId as the key.
Example:
local datastore = DataStoreService:GetDataStore("PlayerData")
--in some playeradded event or some other event
local fetchedData = datastore:GetAsync(player.UserId)
--saving
datastore:SetAsync(player.UserId, data)
OOOOOOOOOOOHHHHH THANK YOU SO MUCH I think I figured out the problem because I have like 5 Datastore and I use GetAsync like 10 to 20 times when player leave and join. Also, I store their data as values inside the player instance so both of these factors might have lead to the data losses. By the way, how do I use Datastore2 to store a dictionary? I can’t understand the article so can u give me an example of saving and loading a dictionary with Datastore2 please? Thank you!