For several days I have been wondering why this method of saving player data doesn't work. Can anyone try this method out, and vouch that it doesn't work?
What would you need to do to test:
1) Create a ModuleScript
2) Place the ModuleScript inside the ServerStorage
3) Paste this code unedited, directly from the wiki inside the ModuleScript:
-- Set up table to return to any script that requires this module script local PlayerStatManager = {} local DataStoreService = game:GetService("DataStoreService") local playerData = DataStoreService:GetDataStore("PlayerData") -- Table to hold player information for the current session local sessionData = {} local AUTOSAVE_INTERVAL = 60 -- Function that other scripts can call to change a player's stats function PlayerStatManager:ChangeStat(player, statName, value) assert(typeof(sessionData[playerUserId][statName]) == typeof(value), "ChangeStat error: types do not match") local playerUserId = "Player_" .. player.UserId if typeof(sessionData[playerUserId][statName]) == "number" then sessionData[playerUserId][statName] = sessionData[playerUserId][statName] + value else sessionData[playerUserId][statName] = value end end -- Function to add player to the 'sessionData' table local function setupPlayerData(player) local playerUserId = "Player_" .. player.UserId local data local success, err = pcall(function() playerData:UpdateAsync(playerUserId, function(playerData) data = playerData end) end) if success then if data then -- Data exists for this player sessionData[playerUserId] = data else -- Data store is working, but no current data for this player sessionData[playerUserId] = {Money=0, Experience=0} end else warn("Cannot set up data for player!") end end -- Function to save player's data local function savePlayerData(playerUserId) if sessionData[playerUserId] then local success, err = pcall(function() playerData:SetAsync(playerUserId, sessionData[playerUserId]) end) if not success then warn("Cannot save data for player!") end end end -- Function to save player data on exit local function saveOnExit(player) local playerUserId = "Player_" .. player.UserId savePlayerData(playerUserId) end -- Function to periodically save player data local function autoSave() while wait(AUTOSAVE_INTERVAL) do for playerUserId, data in pairs(sessionData) do savePlayerData(playerUserId) end end end -- Start running 'autoSave()' function in the background spawn(autoSave) -- Connect 'setupPlayerData()' function to 'PlayerAdded' event game.Players.PlayerAdded:Connect(setupPlayerData) -- Connect 'saveOnExit()' function to 'PlayerRemoving' event game.Players.PlayerRemoving:Connect(saveOnExit) return PlayerStatManager
4) Create a Script and place it inside of the ServerScriptService
5) Copy this code into the script:
local serverstorage = game:GetService("ServerStorage") local module = require(serverstorage.ModuleScript) game:GetService("Players").PlayerAdded:Connect(function(player) local stats = Instance.new("Folder") stats.Name = 'leaderstats' stats.Parent = player local money = Instance.new("NumberValue") money.Name = 'Money' money.Parent = stats local experience = Instance.new("NumberValue") experience.Name = 'Experience' experience.Parent = stats module:ChangeStat(player, 'Money', 5) end)
6) Check 'Enable Studio Access to API Services' located in the Configure this game settings.
7) Report back your findings.
Any help would be appreciated, thanks.
They have a mistake in their code that the Script Analysis window finds immediately -- playerUserId
does not exist at the time of the assert - the assert line needs to be moved down one line.
Also, note that the script doesn't do anything obvious by default - it doesn't connect to any sort of leaderstats
or print out any values. If you don't call ChangeStat
or otherwise modify sessionData
yourself, the Money
and Experience
it's saving will always stay at 0. Now, in your second script, you do call ChangeStat
, but the wiki's script isn't connected to the leaderstats in any way, and you don't read from sessionData
(which you can't because they didn't create a GetStat
function). You'll have to make changes to the original script so that you can update the leaderboard when a player's data is returned and so that any changes you make to the leaderboard are reflected in the sessionData
table. Merging your leaderboard and datastore scripts might be sensible here.
One more thing - the wiki script has a memory leak. When a player leaves the game, their session data should be removed. saveOnExit
should therefore be:
local function saveOnExit(player) local playerUserId = "Player_" .. player.UserId if sessionData[playerUserId] then savePlayerData(playerUserId) sessionData[playerUserId] = nil end end