I don't know if I have got the difference of
:UpdateAsync()
and:SetAsync()
right...
I want to show an example of how I think they should be used, can someone let me know if I am correct?
Using only SetAsync()
:
Player1 starts the game, and the method :SetAsync()
saves this table:
{ Money =100, Life = 50, Mana = 50; }
After that, he uses :SetAsync()
again to overwrite the data with this new table:
{ Money = 150, Life = 75; }
The final data:
{ Money = 150, Life = 75; }
The Mana
value was removed because it wasn't supplied through :SetAsync()
the second time.
When you use UpdateAsync
, you supply your own function that takes the argument of the player's old value. You return what the new value will be. Setting the Async will completely clear it and replace the saved data with the new one; therefore, your first example is correct. If you used UpdateAsync, it all comes down to what the function is.
local DataStore = game:GetService("DataStoreService"):GetDataStore("Stats") --Assume that "plyr" is a variable of a player. This script is also supposed to be a server sided script, so you can get plyr by using events such as "PlayerAdded". --Assume that this data store's old data was {["Money"] = 100, ["Life"] = 50, ["Mana"] = 50} DataStore:SetAsync("User_"..plyr.UserId, {["Money"] = 150, ["Life"] = 75})
No matter what the previous data was, whether it was an integer, BrickColor or even nil, it is now completely wiped and replaced with the new information.
It's like as if you had a variable and you've set it to something else.
local variable = 10 --... some lines of code later... variable = "Now I am a string!" print(variable)
Now I am a string!
With UpdateAsync, it works however you'd like. It takes 2 arguments: the key and then the function used to manipulate that key. The function also has a single argument which is the old value.
--Make the same assumptions as before plus the DataStore variable exists and is valid. DataStore:UpdateAsync("User_"..plyr.UserId, function(oldTable) oldTable["Money"] = 150 oldTable["Life"] = 75 return oldTable end)
Now in this example, the function is editing the table's contents without completely overriding it. Again, the second argument is a function; therefore, UpdateAsync
does whatever you want it do.
DataStore:UpdateAsync("User_"..plyr.UserId, function(oldTable) if oldTable then oldTable["Money"] = 150 oldTable["Life"] = 75 return oldTable else return {["Mana"] = 50} --Change this table to have all default values --or values of new players who are playing for the first time. end end) --Or... local oldTable = DataStore:GetAsync("User_"..plyr.UserId) or {["Mana"] = 50} ---You can set default stats here... oldTable["Money"] = 150 oldTable["Life"] = 75 DataStore:SetAsync("User_"..plyr.UserId, oldTable)
Both result in the same outcome.
So, both can do the same depending on how you code. Neat. Is there situations where you use one over the other? UpdateAsync
is great, but the function that you put inside of it cannot yield at all. For example, you cannot use wait
. You can use SetAsync
in situations where you'd want a yield for whatever reason. UpdateAsync
is great for functions where the previous value is important. For example, a function that adds 50 money every minute in the game. UpdateAsync
is also better for situations where you have code that is using GetAsync
and then using that information almost immediately afterwards to SetAsync
. Use UpdateAsync
in this case as you already get the old value by default as a variable with this function, and GetAsync
can sometimes return cached or old data. If another script is changing the same DataStore with the same key, you might also want to use UpdateAsync
to avoid situations where a player gets money in game, but you save money data from 30 seconds ago.
IncrementAsync
is also great for a money system like this, you should look into it! It's not useful in this case, however, where the data is a table and not a number like an integer.