[SOLVED] "Workspace.Gaining Part.Script:3: attempt to index nil with 'leaderstats'"

Hello guys, I had this issue while helping @nosensehemor.

So me and Nonsense was working to do a Race Clicker Game until this issue happened.

Script:

function touch()
	script.Parent.Touched:Once(function()
		game.Players.LocalPlayer.leaderstats.Money.Value = game.Players.LocalPlayer.leaderstats.Money.Value + 100
		game.Players.LocalPlayer.leaderstats.Points.Value = game.Players.LocalPlayer.leaderstats.Points.Value + 1
	end)
end

return touch()

Video:

So yeah guys, any help is appreciated.

1 Like

Errors aside, you should not be changing leaderstats values on the client. If you change them on the client, they are not replicated to the server. Try using RemoteEvents.

Look at the data:

local Data = game:GetService("DataStoreService"):GetDataStore("thatisadata")

game.Players.PlayerAdded:Connect(function(plr)
	
	local folder = Instance.new("Folder", plr)
	folder.Name = "leaderstats"
	
	local Money = Instance.new("NumberValue", folder)
	Money.Value = 0
	Money.Name = "Money"
	
	local RACE_PLAYED = Instance.new("NumberValue", folder)
	RACE_PLAYED.Value = 0
	RACE_PLAYED.Name = "Race Played"
	
	local Points = Instance.new("NumberValue", folder)
	Points.Value = 0
	Points.Name = "Points"
	
	local Speed = Instance.new("NumberValue", folder)
	Speed.Value = 10
	Speed.Name = "Speed"
	
	local dataload = Data:GetAsync(tostring(plr.UserId))
	
	if dataload then
		Money.Value = dataload[1]
		RACE_PLAYED.Value = dataload[2]
		Points.Value = dataload[3]
		Speed.Value = dataload[4]
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	Data:SetAsync(tostring(plr.UserId),{
		plr.leaderstats.Money.Value,
		plr.leaderstats["Race Played"].Value,
		plr.leaderstats.Points.Value,
		plr.leaderstats.Speed.Value
	})
end)

Also the line that makes you slower is this line:

game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = game.Players.LocalPlayer.leaderstats.Speed.Value

The slower LocalScript is not the issue it’s the Gaining that’s the issue.

As I stated earlier, new data is never going to save if you are changing it on the client. You must use a RemoteEvent or RemoteFunction to tell the server that the client has done something that requires the value to be changed. Secondly, you do not need to run the touch function on the client, you could just run it on the server and make a debounce for each individual player.

You are trying to access the LocalPlayer on the server side when it doesn’t exist.

BasePart.Touched
has a parameter that stands a part which touched the BasePart, we can use that to find the character, and get the player with GetPlayerFromCharacter to access the leaderstats on the serverside.

Try this:

function touch()
	script.Parent.Touched:Once(function(hit)
		local characterModel = hit:FindFirstAncestorWhichIsA("Model")
		
		if characterModel and characterModel:FindFirstChildWhichIsA("Humanoid") then
			local playerFromCharacter = game.Players:GetPlayerFromCharacter(characterModel)
			
			if playerFromCharacter then
				playerFromCharacter.leaderstats.Money.Value = playerFromCharacter.leaderstats.Money.Value + 100
				playerFromCharacter.leaderstats.Points.Value = playerFromCharacter.leaderstats.Points.Value + 1
			end
		end
	end)
end

return touch()
1 Like

It’s not the thread topic, but it concerns me that you save a player’s data in an array rather then a dictionary. How will you know which value is which unless you constantly reference it in comments? I would suggest reformatting your main datastore handler to save and grab player values with the keys being easily readable not only from the server but also to you.

if dataload then
	Money.Value = dataload["Money"]
	RACE_PLAYED.Value = dataload["RacePlayed"]
	Points.Value = dataload["Points"]
	Speed.Value = dataload["Speed"]
end
game.Players.PlayerRemoving:Connect(function(plr)
	Data:SetAsync(tostring(plr.UserId),{
		Money = plr.leaderstats.Money.Value,
		RacePlayed = plr.leaderstats["Race Played"].Value,
		Points = plr.leaderstats.Points.Value,
		Speed = plr.leaderstats.Speed.Value
	})
end)

Maybe something like this? Not required and absolutely up to you, it will just make it easier for you to read your data in the future.

1 Like

Wow, thank you.

@exwumm, Thanks to try to help me.
@seancool07777, Thanks to try to help me.
@IVoidstarI, Thanks for the help !

But, you forgot to put “.Value” in: “Money”; “RACE_PLAYED”; “Points” and “Speed”.

Change: RacePlayed to: RACE_PLAYED.

The Speed is completely Broken by this script.

I wrote my script based on what you sent. The dictionary keys should not matter to the rest of the values if you are grabbing data from them. If it broke on the first time you inserted my script, then it would, because it’s grabbing your old values. Try and commenting out the if dataload then conditional, leaving the game so it saves your data properly, then remove the comment and rejoin with the new data. You can also just edit the keys yourself to what you are comfortable with.

If you don’t want to do that, then here’s a backwards compatible conditional with your old set.

if dataload then
	Money.Value = dataload["Money"] or dataload[1]
	RACE_PLAYED.Value = dataload["RacePlayed"] or dataload[2]
	Points.Value = dataload["Points"] or dataload[3]
	Speed.Value = dataload["Speed"] or dataload[4]
end