How to use the PlayerAdded event without it changing the player's data?

Basically when I try to use the PlayerAdded event to detect if a player has spawned in game, it affects my other script which contains datastore coding and that script doesn’t work. How can I prevent this from happening??

1 Like

I don’t know but I normally make all my datastores and everything all inside one server script or a module then just add onto it from that module / script.

2 Likes

Is there any otther way to detect if a player now spawned into the game??

1 Like

If you want to check when a character spawns/loads in you can use the character added event (unsure if that is what ur looking for).

Example Code:

game.Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		pairs("Runs character stuff here")
	end)
end)

Can you explain why the PlayerAdded event is causing an issue though? I don’t really understand why using PlayerAdded in a different script why this is affecting the player data. To be honest it sound more like some type of code in your game is editing the player data rather then the playerAdded event causing the issue.

1 Like

Theoretically, you could run a :ChildAdded(ChildThatWasAdded) function on the player service. The argument detected would be the player.

1 Like

if you are using a seperate script it shouldn’t affect your other coding. With this are you changing a value that is being used by the other script? Like the others have said, if you want a character to be recognized when they spawn you can edit directly inside of your other script like so, this way they run together.

game:GetService('Players').PlayerAdded:Connect(function(plr)

    --// Datastore stuff here blah blah blah

    --// A little savin' loop here

    while task.wait(15) do
        --// Saves the player(s) data every 15 or so seconds
    end

    --// All your other code to run down here outside of the datastore stuff.

    plr.CharacterAdded:Connect(function(char)
        --// Player(s) Character was added to the workspace
    end)
end)

If this doesn’t make sense, you aren’t providing all the information we need to assist you and we need more information based off of what you are doing with your code to further assist you.

To explain further, basically I am trying to get a sound to play when a player touches a new checkpoint. I don’t want the sound to be re-played if they rejoin the game and spawn on that checkpoint that they touched before. I managed to come up with something but it is quite inefficient, especially for maybe older PCs.

This is the script:

local CKsound = workspace.SoundLibrary.CheckpointSound
local Players = game:GetService("Players")
local Time = {}

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(char)
		wait(char)
		Time[tostring(player.UserId)] = os.time()
		local play = false
		local  debounce = false
		local LevelName = script.Parent.Parent.Parent.Parent.Checkpoints["2"]
		local PlayerLevel = player:WaitForChild("leaderstats").Level
		wait(PlayerLevel)
		print("Online", player)	



		script.Parent.Touched:Connect(function(hit)
			local Player = Players:GetPlayerFromCharacter(hit.Parent)
			if Player ~= nil and debounce == false then
				debounce = true
				print("ACTIVE")

				if not Player then return end


				if Player and play == false then	
					if LevelName ~= nil then			
						print("Activated")
						print("Part Name is", LevelName, "and Player Level is ", PlayerLevel.Value)


						if os.time() - Time[tostring(player.UserId)] <= 3 and LevelName.Name == PlayerLevel.Value then							
							play = false								
							CKsound:Stop()
							print(player.Name, "has spawned for", os.time() - Time[tostring(player.UserId)], "seconds")							
							print(player.Name, "has spawned on same checkpoint")	
						elseif os.time() - Time[tostring(player.UserId)] > 3 and LevelName.Name == PlayerLevel.Value then
							play = true
							CKsound:Play()		
							print("Checkpoint reached")
						elseif LevelName.Name ~= PlayerLevel.Value then	
							play = false				
							CKsound:Stop()			
							print("Checkpoint not reached")
						end	
					end
				end



				PlayerLevel:GetPropertyChangedSignal("Value"):Connect(function()
					print("Part Name is", LevelName, "and Player Level is ", PlayerLevel.Value)	
					if LevelName.Name == PlayerLevel.Value then
						play = true
						CKsound:Play()		
						print("Checkpoint reached")
					else
						if LevelName.Name ~= PlayerLevel.Value then	
							play = false		
							CKsound:Stop()
							print("Checkpoint not reached")	
						end
					end	
				end)
			end
			if Player == nil or (Player == nil and debounce == true) then
				debounce = false
				print("Touch Reset")
			end
		end)
	end)
end)

I used os.time() to kind of solve the issue but if you have any better way of making the script more efficient better overall, let me know.

Oh I also fixed the datastore issue. It wasn’t this script that was affecting it. Also, can you be able to tell the time that a player has spawned into the game??

Wouldn’t that just be the moment when CharacterAdded fires?

True, but it’s inconsistent. See for this piece of the script:

	if char and LevelName.Name == PlayerLevel.Value then							
						play = false								
						CKsound:Stop()
						print(player.Name, "has spawned for", os.time() - Time[tostring(player.UserId)], "seconds")							
						print(player.Name, "has spawned on same checkpoint")	
						elseif LevelName.Name == PlayerLevel.Value then
						play = true
						CKsound:Play()		
						print("Checkpoint reached")
					elseif LevelName.Name ~= PlayerLevel.Value then	
						play = false				
						CKsound:Stop()			
						print("Checkpoint not reached")
					end	
				end
			end

It would work if a player spawns on the same checkpoint that they reached before leaving the game and the sound would not replay but say for instance, I reset my game progress and returned to the first checkpoint and I hop to the next checkpoint, sometimes, this piece of coding doesn’t work:

	elseif LevelName.Name == PlayerLevel.Value then
						play = true
						CKsound:Play()		
						print("Checkpoint reached")

and instead, this piece of coding would activate again:

	if char and LevelName.Name == PlayerLevel.Value then							
						play = false								
						CKsound:Stop()
						print(player.Name, "has spawned for", os.time() - Time[tostring(player.UserId)], "seconds")							
						print(player.Name, "has spawned on same checkpoint")

I need a proper condition for the line:

elseif LevelName.Name == PlayerLevel.Value then

If there’s a way to state that a player was in the game for some time and hasn’t now spawned into the game, that could help to polish the condition.

I could send a video if you want to show what I am talking about if you still don’t understand.

yea a video might help, I’m just a little confused

If you’re looking to check if a player spawned in for the first time ever:

PlayerFirstRespawn={}

--in player.charadded


if not PlayerFirstRespawn[player.Name] then 
-- this is the player's first time spawning since we do not have PlayerFirstRespawn[player.Name]
PlayerFirstRespawn[player.Name]=true
end

--note you should garbage collect the table whenever the player leaves. on playerremoving
1 Like

What are you trying to do here?

I forgot to take that out of the code

This is basically what I wanted, thanks man!

Fixed up the script to this:

local CKsound = workspace.SoundLibrary.CheckpointSound
local Players = game:GetService("Players")
local connection

game.Players.PlayerAdded:Connect(function(player)
	connection = player.CharacterAdded:Connect(function(Char)
		local CharSpawn = Char
		CharSpawn = {}
		local PlayerLevel = player:WaitForChild("leaderstats").Level
		wait(PlayerLevel)
		local play = false
		local  debounce = false
		local LevelName = script.Parent.Parent.Parent.Parent.Checkpoints["2"]
		print("Online", player)	

		if not CharSpawn[player.Name] and LevelName.Name ~= PlayerLevel.Value then
			CharSpawn[player.Name] = true
			print(player.Name, "has spawned on a different checkpoint")
		end
		
		script.Parent.Touched:Connect(function(hit)
			local Player = Players:GetPlayerFromCharacter(hit.Parent)
			if Player ~= nil and debounce == false then
				debounce = true
				print("ACTIVE")

				if not Player then return end


				if Player and play == false then	
					if LevelName ~= nil then			
						print("Activated")
						print("Part Name is", LevelName, "and Player Level is ", PlayerLevel.Value)
						
						
							if not CharSpawn[player.Name] and LevelName.Name == PlayerLevel.Value then
								play = false													
								print(player.Name, "has spawned on same checkpoint")
							end
							
							
							if CharSpawn[player.Name] == true and LevelName.Name == PlayerLevel.Value then
								play = true
								CKsound:Play()		
								print("Checkpoint reached")
							else
								if CharSpawn[player.Name] == true and LevelName.Name ~= PlayerLevel.Value then	
									play = false	
									print("Checkpoint not reached")
								end	
							end
					
				
						PlayerLevel:GetPropertyChangedSignal("Value"):Connect(function()
							print("Part Name is", LevelName, "and Player Level is ", PlayerLevel.Value)	
							if LevelName.Name == PlayerLevel.Value then
								play = true
								CKsound:Play()		
								print("Checkpoint reached")
							else
								if LevelName.Name ~= PlayerLevel.Value then	
									play = false		
									print("Checkpoint not reached")	
								end
							end	
						end)
					end
				end
				if Player == nil or (Player == nil and debounce == true) then
					debounce = false
					print("Touch Reset")
				end
			end	
		end)
	end)
end)

Players.PlayerRemoving:Connect(function(plr)
	connection:Disconnect()
	print(plr, "left")
end)

Lemme know if any adjustments need to be made to it so that it wouldn’t cause lag or so that it would work more efficiently.

did it work? usually the table would be outside all functions so it would be near local connection for the intended functionality to work.

I also don’t believe you need to delete the connection in removing, just

table.remove(CharSpawn, table.find(CharSpawn, player.Name)

if you do it my way anyway, I don’t see how the current method you have works?

I’ve made the adjustments based off your corrections/suggestions and the script is working more efficiently now. Thx alot man! It was working before but with these changes, it is working better now.