Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Why does this death counter with save not work?

I dont know whats wrong, here is the code:

local DataStoreService = game:GetService("DataStoreService")
local playerDeathsStore = DataStoreService:GetDataStore("PlayerDeaths")
local player = game.Players.LocalPlayer
local playername = player.Name

pcall (function()
	playerDeathsStore:SetAsync("PlayerDeaths", _G.died)
end)

if _G.died then
   _G.died = _G.died + 1
else
   _G.died = 0	
end

script.Parent.Text = "You died ".. playerDeathsStore:GetAsync(playername) .." times!"

while true do
   playerDeathsStore:UpdateAsync(playername, _G.died)
end

while wait(1) do
	print(_G.died)
end

3 answers

There are a few problems along with some general logic issues. You can't use DataStoreService in a LocalScript. If you aren't, then you can't get LocalPlayer in a normal script. Since you said your script isn't crashing, I'm going to assume it breaks before that while statement without a wait, else you'd be crashing. You have not set a key for the player, therefore you'd just be saving the same key over and over again to one store 'PlayerDeaths. You shouldn't update _G.died in a while statement since there's a limit. Finally, I recommend using a NumberValue placed in the player V.S. a shared variable since there are restrictions between Local and server scripts.

First, place a Script in ServerScriptService. This script will place the NumberValue in the player and load their deaths to it. We use this to keep track of the deaths and display it in the GUI.

Put a LocalScript in StarterCharacterScripts. Put a Script in the LocalScript. The LocalScript will wait for things to load and the Script will handle everything important, since we don't want exploitation of our value. When FilteringEnabled is on, the client aka you or any player in your game can change things, but it will only be visible by you.

Put your GUI in PlayerGui with a LocalScript in it. The GUI's script will detect a change in the NumberValue. Although this can be exploited, it's not going to do anything but tell you something false if they do. Nothing saves here.

This is a version where it saves every time the player dies. For a large game, this wouldn't be ideal, as there are limits.

This is the code inside the Script in ServerScriptService

local DataStoreService = game:GetService("DataStoreService")
local playerDeathsStore = DataStoreService:GetDataStore("PlayerDeaths")

game.Players.PlayerAdded:Connect(function(player)
	-- Key unique to that player
	local key = string.format("%s_%s", player.Name, player.userId)
	-- Instance the NumberValue into the player who joined
	local deaths = Instance.new("NumberValue", player)
	deaths.Name = "Deaths"
	
	pcall(function()
		-- loads data or sets it to 0 if there is none yet
		local data = playerDeathsStore:GetAsync(key) or 0
		deaths.Value = data
	end)
end)

This is the code inside the LocalScript in StarterCharacterScripts

-- Put in StarterCharacterScript as a LocalScript

local player = game.Players.LocalPlayer
local character = player.Character 
local humanoid = character:WaitForChild("Humanoid")
local deaths = player:WaitForChild("Deaths")
local RemoteEvent = script:WaitForChild('RemoteEvent')

-- Fire the RemoteEvent when we die.
humanoid.Died:Connect(function()
	RemoteEvent:FireServer(player)
end)

This is the code inside the Script placed in the LocalScript

local DataStoreService = game:GetService("DataStoreService")
local playerDeathsStore = DataStoreService:GetDataStore("PlayerDeaths")
local RemoteEvent = Instance.new("RemoteEvent", script.Parent)

local function save(player, new_value, key)
	if pcall(function()
		playerDeathsStore:UpdateAsync(key, function()
			return new_value
		end)
	end) then
		print(string.format("Saved %s deaths [%s]", player.Name, new_value))
	else
		print(string.format("Couldn't save %s deaths.", player.Name, new_value))
	end
end

RemoteEvent.OnServerEvent:connect(function(player)
	-- We don't want to pass the Deaths value from the LocalScript because
	-- it could have been exploited by a player
	local deaths_val = player:findFirstChild("Deaths")
	local key = string.format("%s_%s", player.Name, player.userId)
	if deaths_val then 
		deaths_val.Value = deaths_val.Value + 1
		save(player, deaths_val.Value, key)
	end
end)
local DataStoreService = game:GetService("DataStoreService")
local playerDeathsStore = DataStoreService:GetDataStore("PlayerDeaths")
local player = game.Players.LocalPlayer
local playername = player.Name

pcall (function()
    playerDeathsStore:SetAsync("PlayerDeaths", _G.died)
end)

if _G.died then
   _G.died = _G.died + 1
else
   _G.died = 0  
end

script.Parent.Text = "You died ".. playerDeathsStore:GetAsync(playername) .." times!"

_G.died.Changed:connect(function()
   playerDeathsStore:UpdateAsync(playername, _G.died)
script.Parent.Text = "You died ".. playerDeathsStore:GetAsync(playername) .." times!" 
--Delete the above line if you don't want it
end)

while wait(1) do
    print(_G.died)
end

So, try if this works. You weren't very specific with what went wrong, but i can guess two things:

the kill counter not updating and nothing printing.

The problem was, you had a while true loop. That loop kept on looping and never allowed the print to run.

I created and event to replace the loop, and put the text updater inside as well.

If you don't want the counter to update though, take it out of the event

A while loops won't finish until it is true. You don't wan't to have to two while loops in one script. Here is how I fixed it by combine codes (The code below is not tested):

local DataStoreService = game:GetService("DataStoreService")
local playerDeathsStore = DataStoreService:GetDataStore("PlayerDeaths")
local player = game.Players.LocalPlayer
local playername = player.Name

pcall (function()
    playerDeathsStore:SetAsync("PlayerDeaths", _G.died)
end)

while true do
	playerDeathsStore:UpdateAsync(playername, _G.died)
	script.Parent.Text = "You died ".. playerDeathsStore:GetAsync(playername) .." times!"
	
	if _G.died then
		_G.died = _G.died + 1
	else
		_G.died = 0  
	end

	print(_G.died)
end

Yeah... I don't know what I'm doing.

This discussion is preserved as it was. New answers, comments, and votes are closed.