Welp I’ve tried this method before, but it doesn’t work because all the parents of PlayerData and its descendants are set to nil when the PlayerRemoving event triggers. This means that if I attempt to Clone() the PlayerData folder at that point, I can’t access its descendants.
That said, I can Clone() the PlayerData folder before the PlayerRemoving event. However, how would I detect when the player is about to leave in order to handle this properly?
Are you sure? It seems to work for me when I tested it.
local players = game:GetService("Players")
local function playerAdded(player)
local playerData = Instance.new("Folder")
playerData.Name = "PlayerData"
playerData.Parent = player
local cash = Instance.new("IntValue")
cash.Name = "Cash"
cash.Value = 50
cash.Parent = playerData
local cash = Instance.new("IntValue")
cash.Name = "Gems"
cash.Value = 100
cash.Parent = playerData
end
local function playerRemoving(player)
local clonedPlayerData = player.PlayerData:Clone()
task.wait(1) -- to allow parents of the original values to be set to nil by the new behavior
print(clonedPlayerData.Cash, clonedPlayerData.Cash.Value)
print(clonedPlayerData.Gems, clonedPlayerData.Gems.Value)
end
players.PlayerAdded:Connect(playerAdded)
players.PlayerRemoving:Connect(playerRemoving)
game:BindToClose(function() -- to allow player removing function to run
task.wait(2)
end)
To anyone currently wondering, the best alternative way to save data with these new changes would be to parent every piece of data that you want to save under a folder in another instance or service. Recommendations for such would be ReplicatedStorage (so that the client can access data too) and the ServerStorage (to ensure your data is save there).
When the player is removed, you can then first call for a save of all the data within the folder and than afterwards destroy the folder.
I was hoping my game was immune to this change, I tested today and it turns out my datastore script won’t work the way its coded. I’m testing it now. I don’t save much data, but the workaround that I’m using that seems to be working is to just create local variables for all of the data items before calling any async functions.
Its confusing to me what is meant by " This task is deferred and occurs after bound event connections are invoked, including PlayerRemoving ."
What does deferred mean? From my testing you don’t get much time to access the player before its gone. It seems any async call will finish after the player is gone(so if you have more than one async call to save data, the subsequent reference to the player’s children will throw an error)
If cycle through 4 or 5 values that I save in the player and put those into a table (or individual variables would probably work also), then use those variables to make my database async calls then it seems to work. (I guess its deferred long enough to save the values to variables, but not long enough to make more than one async call).
Somebody let me know if i’m doing this wrong or can explain what deferred means, how much time does this give you to access the instance.
abstract pseudo code with Enabled before fix and after ‘fix’:
So I reckon if we have it Enabled we don’t have to do any garbage collection of events connected to Player or Character instances when they leave or character is removed?
Why this update? You could’ve at least set it to disabled for us to make some changes on our script. After that, we can just enabled it. But no, it literally wiped out all of my player’s data. My datastore fires a save function whenever an item is added or destroyed from their inventory. Because of this, the script save function fires after all the items from their inventories being removed or destroyed which ended up saving an empty inventory. Damage has already been done and all of my players are not happy.
Can you explain more? I’m using the DataStore Editor and I don’t see that setting where I could revert the entire datastore rather than doing one by one on each player.
Apologies on the confusion earlier. I mixed up PlayerRemoving with AncenstryChanged. The initial issue was related to AncenstryChanged hence the inability to clone PlayerData upon the event signal fired. Thank you for the reassurance regarding PlayerRemoving. I’ve applied that but ultimately decided to go with DevFofo’s suggestion on handling player’s data entirely within ReplicatedStorage instead.
As DevFofo mentioned, if anyone has alternative methods, please share them—I’d love to find out if there areany more efficient ways to handle this
The issue was that making ‘Enabled’ the Default option negatively affected more experiences than we anticipated, where the experience code was not prepared for destroyed Character or Player, but did not select ‘Disabled’ mode.
If the ‘Enabled’ option doesn’t work for you today, consider switching it to ‘Disabled’ until you have time to adjust to changes instead of leaving the ‘Default’.
We are also in the process of developing a different transition option which will provide most of the benefit, but will keep the Character/Player connected to the children (but will destroy connections).
We will post an update once we select the best path to continue.
Awesome to hear it, although we are all very heated about it, as long we are indeed being heard and given fair options, no real damage should be caused.