Issue with data for multiple players

this keeps changing everyones leaderstat if 1 player hits the part, i want it to only happen to the specific player that hits the part.

	local FinishDetector = workspace:WaitForChild("FinishThing"):WaitForChild("Detector")
	local hasWon = false

	FinishDetector.Touched:Connect(function(hit)
		local character = hit.Parent
		local player = game.Players:GetPlayerFromCharacter(character)

		if player and not hasWon then
			local checkpoint1 = CheckpointsFolder:FindFirstChild("1")
			if checkpoint1 then
				Wins.Value = Wins.Value + 1
				player.leaderstats:FindFirstChild("🕹️Stage").Value = 1
				hasWon = true

				player.Character:SetPrimaryPartCFrame(checkpoint1.CFrame)
				wait(5)
				hasWon = false

				myDataStore:SetAsync(player.UserId, {Stage = 1, Wins = Wins.Value, Deaths = Deaths.Value})
			end
		end
	end)
5 Likes

Where exactly do you define Wins at? If it’s outside the .Touched event then that would be the issue since it isn’t exclusive to the player that touches the part.

Edit: Maybe i misunderstood what you needed. Is it the Stage or Wins that’s incrementing for everyone?

2 Likes

i mean it is, its like inside the MainHandler where the leaderstats is

2 Likes

Try checking if the name of the character is equal to the name of the player. When you do “if player”, I think that is just checking to see if the player exists

    local FinishDetector = workspace:WaitForChild("FinishThing"):WaitForChild("Detector")
	local hasWon = false

	FinishDetector.Touched:Connect(function(hit)
		local character = hit.Parent
		local player = game.Players:GetPlayerFromCharacter(character)

		if character.Name == player.Name and not hasWon then
			local checkpoint1 = CheckpointsFolder:FindFirstChild("1")
			if checkpoint1 then
				Wins.Value = Wins.Value + 1
				player.leaderstats:FindFirstChild("🕹️Stage").Value = 1
				hasWon = true

				player.Character:SetPrimaryPartCFrame(checkpoint1.CFrame)
				wait(5)
				hasWon = false

				myDataStore:SetAsync(player.UserId, {Stage = 1, Wins = Wins.Value, Deaths = Deaths.Value})
			end
		end
	end)
2 Likes

I’ll give that a shot, thanks!

1 Like

Nope, sadly still have 1 win to the other player in the game.

1 Like

is this a localscript or a server script?

1 Like

server its the main handler, here is the full script.

local DataStoreService = game:GetService("DataStoreService")
local myDataStore = DataStoreService:GetDataStore("MyDataStore")
local Rs = game.ReplicatedStorage
local Players = game:GetService("Players")
local Event = Rs:WaitForChild("Events")
local PS = game:GetService("PhysicsService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StartJumpingEvent = ReplicatedStorage.Events:WaitForChild("StartJumping")

local CollisionGroupName = "Players"

PS:RegisterCollisionGroup(CollisionGroupName)
PS:CollisionGroupSetCollidable(CollisionGroupName, CollisionGroupName, false)

Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function(char)

		local function ChangeGroup(Part)
			if Part:IsA("BasePart") then
				PS:SetPartCollisionGroup(Part, CollisionGroupName)
			end
		end

		char.ChildAdded:Connect(ChangeGroup)
		for _, Object in pairs(char:GetChildren()) do
			ChangeGroup(Object)
		end
	end)
end)

game.Players.PlayerAdded:Connect(function(Player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Parent = Player
	leaderstats.Name = "leaderstats"

	local Stage = Instance.new("NumberValue")
	Stage.Parent = leaderstats
	Stage.Name = "🕹️Stage"
	Stage.Value = 1 -- Start at stage 1

	local Wins = Instance.new("NumberValue")
	Wins.Parent = leaderstats
	Wins.Name = "🏆Wins"
	Wins.Value = 0

	local Deaths = Instance.new("NumberValue")
	Deaths.Parent = leaderstats
	Deaths.Name = "💀Deaths"
	Deaths.Value = 0

	local CheckpointsFolder = game.Workspace:WaitForChild("Checkpoints")

	local debounce = false -- Declare debounce variable here

	for i, Checkpoint in pairs(CheckpointsFolder:GetChildren()) do
		Checkpoint.Touched:Connect(function(Hit)
			if Hit.Parent:FindFirstChild("Humanoid") then
				local PlayerHit = game.Players:GetPlayerFromCharacter(Hit.Parent)

				Checkpoint.BrickColor = BrickColor.new("Bright red")

				if PlayerHit.leaderstats:FindFirstChild("🕹️Stage").Value == tonumber(Checkpoint.Name) - 1 then
					PlayerHit.leaderstats:FindFirstChild("🕹️Stage").Value = Checkpoint.Name
					workspace.SoundFx.Success:Play()
					Event.CheckPointEvent:FireClient(Player)
					myDataStore:SetAsync(Player.UserId, {Stage = Stage.Value, Wins = Wins.Value, Deaths = Deaths.Value})
				end
			end
		end)
	end
	local FinishDetector = workspace:WaitForChild("FinishThing"):WaitForChild("Detector")
	local hasWon = false

	FinishDetector.Touched:Connect(function(hit)
		local character = hit.Parent
		local player = game.Players:GetPlayerFromCharacter(character)

		if character.Name == player.Name and not hasWon then
			local checkpoint1 = CheckpointsFolder:FindFirstChild("1")
			if checkpoint1 then
				Wins.Value = Wins.Value + 1
				player.leaderstats:FindFirstChild("🕹️Stage").Value = 1
				hasWon = true

				player.Character:SetPrimaryPartCFrame(checkpoint1.CFrame)
				wait(5)
				hasWon = false

				myDataStore:SetAsync(player.UserId, {Stage = 1, Wins = Wins.Value, Deaths = Deaths.Value})
			end
		end
	end)



	Player.CharacterAdded:Connect(function(Character)
		repeat
			wait()
		until Character:FindFirstChild("HumanoidRootPart")

		local HumanoidRootPart = Character:FindFirstChild("HumanoidRootPart")
		HumanoidRootPart.CFrame = CheckpointsFolder:FindFirstChild(tostring(Stage.Value)).CFrame + Vector3.new(0, 2, 0)

		-- Detect when the player's character dies
		Character:WaitForChild("Humanoid").Died:Connect(function()
			Deaths.Value = Deaths.Value + 1
			-- Save the updated value to the datastore
			myDataStore:SetAsync(Player.UserId, {Stage = Stage.Value, Wins = Wins.Value, Deaths = Deaths.Value})
		end)
	end)

	local data = myDataStore:GetAsync(Player.UserId)
	if data then
		Stage.Value = data.Stage
		Wins.Value = data.Wins
		Deaths.Value = data.Deaths
	end
end)

StartJumpingEvent.OnServerEvent:Connect(function(player)
	StartJumpingEvent:FireClient(player)
end)

local music = game.Workspace.SoundFx["Cartoony A"]
music.Looped = true
music.Parent = workspace
music:Play()

Are you trying to update the Wins for everyone or only the person who triggered the .Touched event?

1 Like

only the person that triggered the event/touched the part

1 Like

I see your issue. I believe this is caused by connecting the .Touched event in a .PlayerAdded event, meaning there is one .Touched event per player that joins. This can result in the values incrementing for everyone, as well as wasting resources since you have a bunch of connections for no reason. Move the .Touched connections outside the .PlayerAdded connection and let me know if that fixes!

2 Likes

How can I modify the code to make it work?

1 Like

I attempted to fix it for you, this should work, but if it doesn’t just let me know. I also changed out the HasWon boolean in favor of an attribute. This just makes it easier to keep track of which boolean belongs to which player without mapping it out.

Edit: For performance reasons, please cache the result of FindFirstChild whenever you can.

local DataStoreService = game:GetService("DataStoreService")
local myDataStore = DataStoreService:GetDataStore("MyDataStore")
local Rs = game.ReplicatedStorage
local Players = game:GetService("Players")
local Event = Rs:WaitForChild("Events")
local PS = game:GetService("PhysicsService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StartJumpingEvent = ReplicatedStorage.Events:WaitForChild("StartJumping")

local CollisionGroupName = "Players"

PS:RegisterCollisionGroup(CollisionGroupName)
PS:CollisionGroupSetCollidable(CollisionGroupName, CollisionGroupName, false)

Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function(char)

		local function ChangeGroup(Part)
			if Part:IsA("BasePart") then
				PS:SetPartCollisionGroup(Part, CollisionGroupName)
			end
		end

		char.ChildAdded:Connect(ChangeGroup)
		for _, Object in pairs(char:GetChildren()) do
			ChangeGroup(Object)
		end
	end)
end)

game.Players.PlayerAdded:Connect(function(Player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Parent = Player
	leaderstats.Name = "leaderstats"

	local Stage = Instance.new("NumberValue")
	Stage.Parent = leaderstats
	Stage.Name = "🕹️Stage"
	Stage.Value = 1 -- Start at stage 1

	local Wins = Instance.new("NumberValue")
	Wins.Parent = leaderstats
	Wins.Name = "🏆Wins"
	Wins.Value = 0

	local Deaths = Instance.new("NumberValue")
	Deaths.Parent = leaderstats
	Deaths.Name = "💀Deaths"
	Deaths.Value = 0

	Player.CharacterAdded:Connect(function(Character)
		repeat
			wait()
		until Character:FindFirstChild("HumanoidRootPart")

		local HumanoidRootPart = Character:FindFirstChild("HumanoidRootPart")
		HumanoidRootPart.CFrame = workspace:WaitForChild("Checkpoints"):FindFirstChild(tostring(Stage.Value)).CFrame + Vector3.new(0, 2, 0)

		-- Detect when the player's character dies
		Character:WaitForChild("Humanoid").Died:Connect(function()
			Deaths.Value = Deaths.Value + 1
			-- Save the updated value to the datastore
			myDataStore:SetAsync(Player.UserId, {Stage = Stage.Value, Wins = Wins.Value, Deaths = Deaths.Value})
		end)
	end)

	local data = myDataStore:GetAsync(Player.UserId)
	if data then
		Stage.Value = data.Stage
		Wins.Value = data.Wins
		Deaths.Value = data.Deaths
	end
end)

StartJumpingEvent.OnServerEvent:Connect(function(player)
	StartJumpingEvent:FireClient(player)
end)

for i, Checkpoint in pairs(workspace:WaitForChild("Checkpoints"):GetChildren()) do
	Checkpoint.Touched:Connect(function(Hit)
		if Hit.Parent:FindFirstChild("Humanoid") then
			local PlayerHit = game.Players:GetPlayerFromCharacter(Hit.Parent)

			Checkpoint.BrickColor = BrickColor.new("Bright red")
			
			local stage = PlayerHit.leaderstats:FindFirstChild("🕹️Stage")
			if stage.Value == tonumber(Checkpoint.Name) - 1 then
				stage.Value = Checkpoint.Name
				workspace.SoundFx.Success:Play()
				Event.CheckPointEvent:FireClient(PlayerHit)

				myDataStore:SetAsync(PlayerHit.UserId, {
					stage.Value,
					Wins = PlayerHit.leaderstats:FindFirstChild("🏆Wins").Value,
					Deaths = PlayerHit.leaderstats:FindFirstChild("💀Deaths").Value
				})
			end
		end
	end)
end

local FinishDetector = workspace:WaitForChild("FinishThing"):WaitForChild("Detector")
FinishDetector.Touched:Connect(function(hit)
	local character = hit.Parent
	local player = game.Players:GetPlayerFromCharacter(character)

	if character.Name == player.Name and not player:GetAttribute("HasWon") then
		local checkpoint1 = workspace:WaitForChild("Checkpoints"):FindFirstChild("1")
		if checkpoint1 then
			local wins = player.leaderstats:FindFirstChild("🏆Wins")
			wins.Value += 1

			player.leaderstats:FindFirstChild("🕹️Stage").Value = 1
			player:SetAttribute("HasWon", true)

			player.Character:SetPrimaryPartCFrame(checkpoint1.CFrame)
			task.wait(5)
			player:SetAttribute("HasWon", false)

			myDataStore:SetAsync(player.UserId, {
				Stage = 1,
				Wins = wins.Value,
				Deaths = player.leaderstats:FindFirstChild("💀Deaths").Value
			})
		end
	end
end)

local music = game.Workspace.SoundFx["Cartoony A"]
music.Looped = true
music.Parent = workspace
music:Play()
4 Likes

What does cache the result mean?

It pretty much just means store the result in a variable.

local cachedResult = instance:FindFirstChild("Child")

Ahhh, I understand. Its to optimize the need to find first child multiple times

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.