DataStore won't load even though it says it did already

I have a probably very simple problem but I can’t find a solution.

I made it so my datastore script will print out a message once the data is loaded in. When I join the game, it says that my data has been loaded in but my gems and coins (the currency I have in my game) are still at 0.

I have API services and HTTP requests on.

-->>: Datastore

local dataStoreService = game:GetService("DataStoreService")
local myDataStore = dataStoreService:GetDataStore("MainDataStore")

local playersLeft = 0 

-- Load leaderstats
game.Players.PlayerAdded:Connect(function(player)

	playersLeft = playersLeft + 1
	
	-- Leaderstats 
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	
	-- Coins
	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Parent = leaderstats
	
	-- Gems
	local gems = Instance.new("IntValue")
	gems.Name = "Gems"
	gems.Parent = leaderstats

	-- Load data

	local PlayerUserId = player.UserId -- Player key to store data

	local player_data
	
	-- Data to load in
	local dataTable1 = {
		Coins = player.leaderstats.Coins.Value;
		Gems = player.leaderstats.Gems.Value;
	}
		
	local success, errorMessage = pcall(function()
		player_data = myDataStore:GetAsync(PlayerUserId)
	end)

	-- Load data

	if success then
		coins.Value = dataTable1.Coins
		gems.Value = dataTable1.Gems
		
		print("Loaded in data for "..player.Name.." ("..player.UserId..")") -- It prints out this message when I join even though it isn't true
	else
		print("Error: "..player.Name.."("..player.UserID..") data can't be loaded in")
		warn(errorMessage)
	end
end)

local bindableEvent = Instance.new("BindableEvent")

-- Player leaves
game.Players.PlayerRemoving:Connect(function(player)
	
	local playerUserId = player.UserId -- Player key

	-- Data table
	local dataTable2 = {
		Coins = player.leaderstats.Coins.Value;
		Gems = player.leaderstats.Gems.Value;
	}

	local success, errorMessage = pcall(function()
		myDataStore:SetAsync(playerUserId, dataTable2)

		playersLeft = playersLeft - 1

		bindableEvent:Fire()
	end)

	if success then
		print(player.Name.." ("..player.UserId..")'s data has been loaded in")
	else
		print("Error saving data for "..player.Name.." ("..player.UserId..")")
		warn(errorMessage)
	end
end)

if playersLeft > 0 then
	bindableEvent.Event:Wait()
end

You’re not setting or using the player data that you retrieved from the datastore. You created a dictionary called “dataTable1” then set the coins and gems value to your leaderstat values that you created right above it. By default those intValues are going to be 0. Then in your if success statement, you’re setting the players coins to dataTable1 instead of player_data.Coins.

2 Likes

Test this in the actual game. Studio closes the game before PlayerRemoving runs. To fix this for studio, use game:BindToClose()

local DataStores = game:GetService("DataStoreService")
local DataStore = DataStores:GetDataStore("DataStore")
local Players = game:GetService("Players")
local PlayerCount = #Players:GetPlayers()

local ProtectedCall = pcall
local DoNotSavePlayers = {}

Players.PlayerAdded:Connect(function(Player)
	PlayerCount += 1
	
	local Leaderstats = Instance.new("Folder")
	Leaderstats.Name = "leaderstats"
	Leaderstats.Parent = Player

	local Coins = Instance.new("IntValue")
	Coins.Name = "Coins"
	Coins.Parent = Leaderstats

	local Gems = Instance.new("IntValue")
	Gems.Name = "Gems"
	Gems.Parent = Leaderstats

	local Success, Result = ProtectedCall(function()
		return DataStore:GetAsync("Data_"..Player.UserId)
	end)
	
	if Success then
		if Result then
			if type(Result) == "table" then
				Coins.Value = Result[1]
				Gems.Value = Result[2]
			end
		end
	else
		warn(Result)
		table.insert(DoNotSavePlayers, Player)
	end	
end)

Players.PlayerRemoving:Connect(function(Player)
	PlayerCount -= 1
	
	if table.find(DoNotSavePlayers, Player) then
		return
	end
	
	local Success, Result = ProtectedCall(function()
		return DataStore:SetAsync("Data_"..Player.UserId, {Player.leaderstats.Coins.Value, Player.leaderstats.Gems.Value})
	end)
	
	if Success then
		print(Result)
	else
		warn(Result)
	end
end)

game:BindToClose(function()
	for _, Player in ipairs(Players:GetPlayers()) do
		if table.find(DoNotSavePlayers, Player) then
			return
		end
		
		local Success, Result = ProtectedCall(function()
			return DataStore:SetAsync("Data_"..Player.UserId, {Player.leaderstats.Coins.Value, Player.leaderstats.Gems.Value})
		end)

		if Success then
			print(Result)
		else
			warn(Result)
		end
	end
end)

task.spawn(function()
	while true do
		for Index, Player in ipairs(DoNotSavePlayers) do
			task.wait(60 / #DoNotSavePlayers)
			
			local Success, Result = ProtectedCall(function()
				return DataStore:GetAsync("Data_"..Player.UserId)
			end)

			if Success then
				if Result then
					if type(Result) == "table" then
						Player.leaderstats.Coins.Value = Result[1]
						Player.leaderstats.Gems.Value = Result[2]
						table.remove(DoNotSavePlayers, Index)
					end
				end
			else
				warn(Result)
			end	
		end
	end
end)