My datastore is not working

local players = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")

local database = dataStoreService:GetDataStore("data")
local sessionData = {}

players.PlayerAdded:Connect(function(player)
	local skillFolder = Instance.new("Folder")
	skillFolder.Name = "Skills"
	skillFolder.Parent = player
	local skill = Instance.new("StringValue")
	skill.Name = "Skill"
	skill.Parent = skillFolder
	
	local weaponFolder = Instance.new("Folder")
	weaponFolder.Name = "Weapons"
	weaponFolder.Parent = player
	local weapon = Instance.new("StringValue")
	weapon.Name = "Weapon"
	weapon.Parent = weaponFolder
	weapon.Value = ""
	
	local itemFolder = Instance.new("Folder")
	itemFolder.Name = "Items"
	itemFolder.Parent = player
	local weapon = Instance.new("StringValue")
	weapon.Name = "Item"
	weapon.Parent = itemFolder
	weapon.Value = ""
	
	local skillCollection = Instance.new("Folder")
	skillCollection.Name = "Skill Collection"
	skillCollection.Parent = player
	
	local fireballCollected = Instance.new("BoolValue")
	fireballCollected.Name = "Fireball Collected Status"
	fireballCollected.Parent = skillCollection
	fireballCollected.Value = false
	
	local punchCollected = Instance.new("BoolValue")
	punchCollected.Name = "Punch Collected Status"
	punchCollected.Parent = skillCollection
	punchCollected.Value = false
	
	local earthSpikesCollected = Instance.new("BoolValue")
	earthSpikesCollected.Name = "Earth Spikes Collected Status"
	earthSpikesCollected.Parent = skillCollection
	earthSpikesCollected.Value = false
	
	local blueFireball = Instance.new("BoolValue")
	blueFireball.Name = "Blue Fireball Collected Status"
	blueFireball.Parent = skillCollection
	blueFireball.Value = false
	
	local aquaticTornado = Instance.new("BoolValue")
	aquaticTornado.Name = "Aquatic Tornado Collected Status"
	aquaticTornado.Parent = skillCollection
	aquaticTornado.Value = false
	
	local hollowPurple = Instance.new("BoolValue")
	hollowPurple.Name = "Hollow Purple Collected Status"
	hollowPurple.Parent = skillCollection
	hollowPurple.Value = false
	
	local fighting = Instance.new("BoolValue")
	fighting.Name = "playerFightingCheck"
	fighting.Parent = player
	fighting.Value = false
	
	local success = nil
	local playerData = nil
	local attempt = 1
	
	repeat
		success, playerData = pcall(function()
			return database:GetAsync(player.UserId)
		end)

		attempt += 1
		if not success then
			warn(playerData)
			task.wait(3)
		end
	until success or attempt == 5
	
	if success then
		print("Connected to database")
		if not playerData then
			print("Assigning deafult data")
			playerData = {
				skill.Value
			}
		end
		sessionData[player.UserId] = playerData
	else
		warn("Unable to get data for: " .. player.UserId)
		player:Kick("Unable to load your data. Try again later!")
	end
	
	skill:GetPropertyChangedSignal("Value"):Connect(function()
		sessionData[player.UserId].skill = skill.Value
	end)
end)

players.PlayerRemoving:Connect(function(player)
	if sessionData[player.UserId] then
		local success = nil
		local errorMessage = nil
		local attempt = 1
		
		repeat
			success, errorMessage = pcall(function()
				database:SetAsync(player.UserId, sessionData[player.UserId])
			end)
			
			attempt += 1
			if not success then
				warn(errorMessage)
				task.wait(3)
			end
		until success or attempt == 5
		
		if success then
			print("Data saved for " .. player.Name)
		else
			warn("Unable to save for " .. player.Name)
		end
	end
end)

I don’t get it, how would I make this work?

1 Like

First of all, you have 2 variables named weapon in your leaderstats creations, which leads to confusion,

Second: In the code where you store playerData in sessionData, you’re assigning the skill value directly to the playerData table but not considering the other data you might want to save, you might want to store more data so use a key-value structure like

playerData = {
    Skill = skill.Value
}

You’re connecting a signal to skill:GetPropertyChangedSignal("Value"), but the connection might not properly update sessionData because the key might be incorrect:

sessionData[player.UserId].Skill = skill.Value

To save u a headache, i suggest u to take a deep dive into ProfileService, Saving data is quite easy, accessing it from the client can sometimes be a lil hard but for that there is something called ReplicaService.

1 Like

oh I copy pasted and forgot to replace weapon with item, thanks for pointing that out.

I did everything you told me to do but the data still does not save when I rejoin on Roblox Studio. Here is the updated code:

local players = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")

local database = dataStoreService:GetDataStore("data")
local sessionData = {}

players.PlayerAdded:Connect(function(player)
	local skillFolder = Instance.new("Folder")
	skillFolder.Name = "Skills"
	skillFolder.Parent = player
	local skill = Instance.new("StringValue")
	skill.Name = "Skill"
	skill.Parent = skillFolder
	
	local weaponFolder = Instance.new("Folder")
	weaponFolder.Name = "Weapons"
	weaponFolder.Parent = player
	local weapon = Instance.new("StringValue")
	weapon.Name = "Weapon"
	weapon.Parent = weaponFolder
	weapon.Value = ""
	
	local itemFolder = Instance.new("Folder")
	itemFolder.Name = "Items"
	itemFolder.Parent = player
	local item = Instance.new("StringValue")
	item.Name = "Item"
	item.Parent = itemFolder
	item.Value = ""
	
	local skillCollection = Instance.new("Folder")
	skillCollection.Name = "Skill Collection"
	skillCollection.Parent = player
	
	local fireballCollected = Instance.new("BoolValue")
	fireballCollected.Name = "Fireball Collected Status"
	fireballCollected.Parent = skillCollection
	fireballCollected.Value = false
	
	local punchCollected = Instance.new("BoolValue")
	punchCollected.Name = "Punch Collected Status"
	punchCollected.Parent = skillCollection
	punchCollected.Value = false
	
	local earthSpikesCollected = Instance.new("BoolValue")
	earthSpikesCollected.Name = "Earth Spikes Collected Status"
	earthSpikesCollected.Parent = skillCollection
	earthSpikesCollected.Value = false
	
	local blueFireball = Instance.new("BoolValue")
	blueFireball.Name = "Blue Fireball Collected Status"
	blueFireball.Parent = skillCollection
	blueFireball.Value = false
	
	local aquaticTornado = Instance.new("BoolValue")
	aquaticTornado.Name = "Aquatic Tornado Collected Status"
	aquaticTornado.Parent = skillCollection
	aquaticTornado.Value = false
	
	local hollowPurple = Instance.new("BoolValue")
	hollowPurple.Name = "Hollow Purple Collected Status"
	hollowPurple.Parent = skillCollection
	hollowPurple.Value = false
	
	local fighting = Instance.new("BoolValue")
	fighting.Name = "playerFightingCheck"
	fighting.Parent = player
	fighting.Value = false
	
	local success = nil
	local playerData = nil
	local attempt = 1
	
	repeat
		success, playerData = pcall(function()
			return database:GetAsync(player.UserId)
		end)

		attempt += 1
		if not success then
			warn(playerData)
			task.wait(3)
		end
	until success or attempt == 5
	
	if success then
		print("Connected to database")
		if not playerData then
			print("Assigning deafult data")
			playerData = {
				Skill = skill.Value
			}
		end
		sessionData[player.UserId] = playerData
	else
		warn("Unable to get data for: " .. player.UserId)
		player:Kick("Unable to load your data. Try again later!")
	end
	
	skill:GetPropertyChangedSignal("Value"):Connect(function()
		sessionData[player.UserId].Skill = skill.Value
	end)
end)

players.PlayerRemoving:Connect(function(player)
	if sessionData[player.UserId] then
		local success = nil
		local errorMessage = nil
		local attempt = 1
		
		repeat
			success, errorMessage = pcall(function()
				database:SetAsync(player.UserId, sessionData[player.UserId])
			end)
			
			attempt += 1
			if not success then
				warn(errorMessage)
				task.wait(3)
			end
		until success or attempt == 5
		
		if success then
			print("Data saved for " .. player.Name)
		else
			warn("Unable to save for " .. player.Name)
		end
	end
end)

could it be because I’m testing on Roblox Studio?

Nah thats fine, try this

local players = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")

local database = dataStoreService:GetDataStore("data")
local sessionData = {}

players.PlayerAdded:Connect(function(player)
	-- Create skill folder
	local skillFolder = Instance.new("Folder")
	skillFolder.Name = "Skills"
	skillFolder.Parent = player
	local skill = Instance.new("StringValue")
	skill.Name = "Skill"
	skill.Parent = skillFolder

	-- Create weapon folder
	local weaponFolder = Instance.new("Folder")
	weaponFolder.Name = "Weapons"
	weaponFolder.Parent = player
	local weapon = Instance.new("StringValue")
	weapon.Name = "Weapon"
	weapon.Parent = weaponFolder
	weapon.Value = ""

	-- Create item folder
	local itemFolder = Instance.new("Folder")
	itemFolder.Name = "Items"
	itemFolder.Parent = player
	local item = Instance.new("StringValue")
	item.Name = "Item"
	item.Parent = itemFolder
	item.Value = ""

	-- Create skill collection folder
	local skillCollection = Instance.new("Folder")
	skillCollection.Name = "Skill Collection"
	skillCollection.Parent = player

	local skills = {"Fireball", "Punch", "Earth Spikes", "Blue Fireball", "Aquatic Tornado", "Hollow Purple"}

	for _, skillName in ipairs(skills) do
		local skillStatus = Instance.new("BoolValue")
		skillStatus.Name = skillName .. " Collected Status"
		skillStatus.Parent = skillCollection
		skillStatus.Value = false
	end

	-- Create fighting check
	local fighting = Instance.new("BoolValue")
	fighting.Name = "playerFightingCheck"
	fighting.Parent = player
	fighting.Value = false

	-- Load player data
	local success, playerData
	local attempt = 0

	repeat
		attempt += 1
		success, playerData = pcall(function()
			return database:GetAsync(player.UserId)
		end)

		if not success then
			warn("Failed to load data: " .. playerData)
			task.wait(3)
		end
	until success or attempt >= 5

	if success then
		print("Connected to database")
		if not playerData then
			print("Assigning default data")
			playerData = {
				Skill = skill.Value
			}
		else
			-- Load the saved data into the player's Skill
			skill.Value = playerData.Skill or ""
		end
		sessionData[player.UserId] = playerData
	else
		warn("Unable to get data for: " .. player.UserId)
		player:Kick("Unable to load your data. Try again later!")
	end

	-- Listen for changes to the Skill value
	skill:GetPropertyChangedSignal("Value"):Connect(function()
		if sessionData[player.UserId] then
			sessionData[player.UserId].Skill = skill.Value
		end
	end)
end)

players.PlayerRemoving:Connect(function(player)
	if sessionData[player.UserId] then
		local success, errorMessage
		local attempt = 0

		repeat
			attempt += 1
			success, errorMessage = pcall(function()
				database:SetAsync(player.UserId, sessionData[player.UserId])
			end)

			if not success then
				warn("Failed to save data: " .. errorMessage)
				task.wait(3)
			end
		until success or attempt >= 5

		if success then
			print("Data saved for " .. player.Name)
		else
			warn("Unable to save data for " .. player.Name)
		end

		-- Clean up session data
		sessionData[player.UserId] = nil
	end
end)

1 Like

It didn’t work, I’m pressing the play button on roblox studio and ending the session by pressing the stop button. Also, I checked and the value does change in game, so thats not an issue.

May you run this script for testing purposes, to check if the data actually saves for u, if it doesnt it would be weird since it does for me

I implemented a coin stat that increments by the second

local players = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")

local database = dataStoreService:GetDataStore("data")
local sessionData = {}

players.PlayerAdded:Connect(function(player)
	-- Create leaderstats folder for leaderboard
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	-- Create Coins value to show on leaderboard
	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Parent = leaderstats
	coins.Value = 0

	-- Create skill folder
	local skillFolder = Instance.new("Folder")
	skillFolder.Name = "Skills"
	skillFolder.Parent = player
	local skill = Instance.new("StringValue")
	skill.Name = "Skill"
	skill.Parent = skillFolder

	-- Create weapon folder
	local weaponFolder = Instance.new("Folder")
	weaponFolder.Name = "Weapons"
	weaponFolder.Parent = player
	local weapon = Instance.new("StringValue")
	weapon.Name = "Weapon"
	weapon.Parent = weaponFolder
	weapon.Value = ""

	-- Create item folder
	local itemFolder = Instance.new("Folder")
	itemFolder.Name = "Items"
	itemFolder.Parent = player
	local item = Instance.new("StringValue")
	item.Name = "Item"
	item.Parent = itemFolder
	item.Value = ""

	-- Create skill collection folder
	local skillCollection = Instance.new("Folder")
	skillCollection.Name = "Skill Collection"
	skillCollection.Parent = player

	local skills = {"Fireball", "Punch", "Earth Spikes", "Blue Fireball", "Aquatic Tornado", "Hollow Purple"}

	for _, skillName in ipairs(skills) do
		local skillStatus = Instance.new("BoolValue")
		skillStatus.Name = skillName .. " Collected Status"
		skillStatus.Parent = skillCollection
		skillStatus.Value = false
	end

	-- Create fighting check
	local fighting = Instance.new("BoolValue")
	fighting.Name = "playerFightingCheck"
	fighting.Parent = player
	fighting.Value = false

	-- Load player data
	local success, playerData
	local attempt = 0

	repeat
		attempt += 1
		success, playerData = pcall(function()
			return database:GetAsync(player.UserId)
		end)

		if not success then
			warn("Failed to load data: " .. playerData)
			task.wait(3)
		end
	until success or attempt >= 5

	if success then
		print("Connected to database")
		if not playerData then
			print("Assigning default data")
			playerData = {
				Skill = skill.Value,
				Coins = 0  -- Initialize coins if no data exists
			}
		else
			-- Load the saved data into the player's Skill and Coins
			skill.Value = playerData.Skill or ""
			coins.Value = playerData.Coins or 0
		end
		sessionData[player.UserId] = playerData
	else
		warn("Unable to get data for: " .. player.UserId)
		player:Kick("Unable to load your data. Try again later!")
	end

	-- Increment coins by 1 every second for testing purposes
	while player.Parent do
		coins.Value += 1
		if sessionData[player.UserId] then
			sessionData[player.UserId].Coins = coins.Value
		end
		task.wait(1)  -- Wait for 1 second
	end

	-- Listen for changes to the Skill value
	skill:GetPropertyChangedSignal("Value"):Connect(function()
		if sessionData[player.UserId] then
			sessionData[player.UserId].Skill = skill.Value
		end
	end)
end)

players.PlayerRemoving:Connect(function(player)
	if sessionData[player.UserId] then
		local success, errorMessage
		local attempt = 0

		repeat
			attempt += 1
			success, errorMessage = pcall(function()
				database:SetAsync(player.UserId, sessionData[player.UserId])
			end)

			if not success then
				warn("Failed to save data: " .. errorMessage)
				task.wait(3)
			end
		until success or attempt >= 5

		if success then
			print("Data saved for " .. player.Name)
		else
			warn("Unable to save data for " .. player.Name)
		end

		-- Clean up session data
		sessionData[player.UserId] = nil
	end
end)
1 Like

yes, this worked
29+1cahrcharchar

is it not working because I’m doing Skill = skill.Value, which is basically the same as skill.value = skill.value?

someone please help :sob: :pray:
29+1charchar

I still have not found a solution… Is it because I’m doing all of thsi in Studio?

I still don’t have a solution, please help me put :sob: :pray:

local DataStoreService = game:GetService("DataStoreService")
local dataStore = DataStoreService:GetDataStore("DataStore")
local players = game:GetService("Players")

players.PlayerAdded:Connect(function(player)
	local skillFolder = Instance.new("Folder")
	skillFolder.Name = "Skills"

	local weaponFolder = Instance.new("Folder")
	weaponFolder.Name = "Weapons"

	local itemFolder = Instance.new("Folder")
	itemFolder.Name = "Items"

	local skillCollection = Instance.new("Folder")
	skillCollection.Name = "Skill Collection"

	local fireballCollected = Instance.new("BoolValue")
	fireballCollected.Name = "Fireball Collected Status"

	local punchCollected = Instance.new("BoolValue")
	punchCollected.Name = "Punch Collected Status"

	local earthSpikesCollected = Instance.new("BoolValue")
	earthSpikesCollected.Name = "Earth Spikes Collected Status"

	local blueFireball = Instance.new("BoolValue")
	blueFireball.Name = "Blue Fireball Collected Status"

	local aquaticTornado = Instance.new("BoolValue")
	aquaticTornado.Name = "Aquatic Tornado Collected Status"

	local hollowPurple = Instance.new("BoolValue")
	hollowPurple.Name = "Hollow Purple Collected Status"

	local fighting = Instance.new("BoolValue")
	fighting.Name = "playerFightingCheck"
	
	----
	
	local data = dataStore:GetAsync(player.UserId)
	
	----
	
	skillFolder.Parent = player
	local skill = Instance.new("StringValue")
	skill.Name = "Skill"
	skill.Parent = skillFolder
	skill.Value = ""

	weaponFolder.Parent = player
	local weapon = Instance.new("StringValue")
	weapon.Name = "Weapon"
	weapon.Parent = weaponFolder
	weapon.Value = ""

	itemFolder.Parent = player
	local item = Instance.new("StringValue")
	item.Name = "Item"
	item.Parent = itemFolder
	item.Value = ""

	skillCollection.Parent = player

	fireballCollected.Parent = skillCollection
	fireballCollected.Value = false

	punchCollected.Parent = skillCollection
	punchCollected.Value = false

	earthSpikesCollected.Parent = skillCollection
	earthSpikesCollected.Value = false

	blueFireball.Parent = skillCollection
	blueFireball.Value = false

	aquaticTornado.Parent = skillCollection
	aquaticTornado.Value = false

	hollowPurple.Parent = skillCollection
	hollowPurple.Value = false

	fighting.Parent = player
	fighting.Value = false

end)

I revised the code but now I’m stuck… How would I save the data and load it in now?

You should be adding game:BindToClose() as when you exit the game like for example Alt+F4 it doesn’t save in time.

Edit: Doing this function will make the server save your data before the roblox client shuts down.

1 Like

Here is how you would do that.

game:BindToClose(function()
	for i, player in ipairs(game.Players:GetPlayers()) do
if sessionData[player.UserId] then
		local success, errorMessage
		local attempt = 0

		repeat
			attempt += 1
			success, errorMessage = pcall(function()
				database:SetAsync(player.UserId, sessionData[player.UserId])
			end)

			if not success then
				warn("Failed to save data: " .. errorMessage)
				task.wait(3)
			end
		until success or attempt >= 5

		if success then
			print("Data saved for " .. player.Name)
		else
			warn("Unable to save data for " .. player.Name)
		end

		-- Clean up session data
		sessionData[player.UserId] = nil
	end
end
end)
1 Like

I’ll try this out, thanks! I also heard a few minutes ago that I should parent objects after I declare Async or something so that the script doesn’t get confused. Is this true?

1 Like

Yes that is true, but in your scenario I don’t think it’s necessary as you are saving sessionData as the table.

1 Like

I replaced my players.PlayerRemoving… code with yours and it still isn’t working

1 Like

Yeah but you still need to have players.PlayerRemoving and also have the bindtoclose func.