Placing markers on teammates doesn't always work

You can write your topic however you want, but you need to answer these questions:

  1. I want all teammates to have a marker placed on their head

  2. Sometimes markers do not get placed with no error

  3. Tried thinking of all the possible solutions, the only one is to just make a loop rather than use listeners

The script below is full (missing some basic declarations), found in a ScreenGui with ResetOnSpawn enabled. I think I have all the necessary connections made as well the necessary disconnections. It should, when you spawn manage all the teammates correctly but somehow a lot of people are missing the markers. Am I doing something wrong?

--Clone and place a marker onto the part
local function placeMarker(part, marker)
	local markerClone = marker:Clone()
	markerClone.Parent = part
	markerClone.Active = true
	table.insert(markerCollection, markerClone)
	return markerClone
end

--Handle a teammate
local function handleCharacter(character)
	local head = character:WaitForChild("Head")
	local thisTeammateMarker = placeMarker(head, teammateMarker)
	thisTeammateMarker.TextLabel.Text = character.Name
end

--Create a marker adding connection for the provided player
local function setupCharacterAddedConnection(player)
	local connection
	connection = player.CharacterAdded:Connect(function(characterAdded)
		if player.Team == Player.Team then
			handleCharacter(characterAdded)
		elseif connection then
			print("disconnected for different team for " .. player.Name)
			connection:Disconnect() --Disconnect if player is no longer a teammate
		end
	end)
end

--Add markers and make connections for current teammates
for _, teammate in pairs(Player.Team:GetPlayers()) do
	if teammate.Character and teammate ~= Player then
		handleCharacter(teammate.Character)
	end
	setupCharacterAddedConnection(teammate)
end

--Listen to new teammates added to create a connection
Player.Team.PlayerAdded:Connect(function(playerAdded)
	setupCharacterAddedConnection(playerAdded)
end)
2 Likes

I’m pretty sure the connection is being reset every time the “setupCharacterAddedConnection” function is run, meaning that it’s actually only listening for the player who most recently joined the Team to respawn.

To resolve this, consider creating a table outside of the function where the connections are stored per player. This will ensure that their event connection is not overridden when other players activate the function by joining the LocalPlayer’s Team:

local playerConnections = {}

local function setupCharacterAddedConnection(player)
	playerConnections[player] = player.CharacterAdded:Connect(function(characterAdded)
		if player.Team == Player.Team then
			handleCharacter(characterAdded)
		elseif playerConnections[player] ~= nil then
			print("disconnected for different team for " .. player.Name)
			playerConnections[player]:Disconnect() --Disconnect if player is no longer a teammate
            playerConnections[player] = nil
		end
	end)
end

If that works out well, also make sure to disconnect those connections upon PlayerRemoving to ensure that it’s properly cleaned up:

Players.PlayerRemoving:Connect(function(player)
    local connectionCheck = playerConnections[player]

    if connectionCheck then
        connectionCheck:Disconnect()
        connectionCheck = nil
    end
end)
1 Like

Thank you, this is an interesting suggestion that I haven’t even considered. I thought that since the connection variable is created inside the function, connections will not override each other. The problem is I cannot replicate the moment the script starts working, I just know it doesn’t work sometimes. I’ll try this and will make sure to mark this as a solution if it works.

1 Like

Thanks for pointing that out, as that made me realize I was mistaken and was thinking of it backwards (you are correct in that it is not overridden; went into Roblox Studio to quickly confirm that). That’s my bad! As a result, the suggestion I made above is likely not a solution for this.


For some additional context, does the player’s Character happen to be respawned whenever they join a new team? I know you mentioned that ResetOnSpawn is enabled for the ScreenGui where this LocalScript code is (which means that even though the LocalScript is not listening for a player to change Teams, it should stay pretty up-to-date with the player’s current team if they respawn often), however, maybe the issue could stem from situations where a player joins a new team and does not respawn (meaning the LocalScript doesn’t know it needs to rerun the “setupCharacterAddedConnection” function for all of their new teammates that happened to already be on Team that they joined)?

If that’s the case though, that’s something that should be resolved upon the player’s next respawn, since the “refreshed” LocalScript would run from top to bottom again and be updated to their new Team.


Another important thing to know would be: how often does it fail to place the marker on teammates? Is it pretty random or do you notice it happening more often in certain situations (such as after joining a new team).

1 Like

There are, whenever a player changes the team, they are despawned completely, and will stay like that until they choose to spawn. The LocalScript runs when the character loads and handles the list teammates in that moment, meaning it shouldn’t matter when the player chooses to spawn in.

This is an interesting question, the game is a 50 player, 25v25 KOTH. Once the match ends everyone is reset and moved to team Neutral. After the new map is voted for and people join teams, a lot of markers are not loaded. This makes me think that this is happens when a lot of people join a team and spawn in at the same time, but at the same time, the way the script is written should prevent anything like that from mattering.

1 Like

I played the game for some time earlier to see if and when I would encounter that issue. I went through around half of an ongoing match and it never seemed to happen. But, like you mentioned, it wasn’t until the start of a brand new match that it seemed to occur:


Example #1 (Joined a team and spawned in)

Example #2 (Displaying what appeared in the Developer Console)


Example #3 (Example of another Character loading in without the Teammate nametag)

Example #4 (Resetting my Character to see if the nametags will appear upon respawning)

Example #5 (The Teammate nametags began to consistently appear after respawning)

Example #6 (Displaying what appeared in the Developer Console again)


After thinking about it some more, I’m still not fully sure what could be causing it to happen, but here are some possible things to try:

  1. Swap the order that these are run in:

To this:

Player.Team.PlayerAdded:Connect(function(playerAdded)
	setupCharacterAddedConnection(playerAdded)
end)

for _, teammate in pairs(Player.Team:GetPlayers()) do
	if teammate.Character and teammate ~= Player then
		handleCharacter(teammate.Character)
	end
	setupCharacterAddedConnection(teammate)
end

So that the Team.PlayerAdded event is connected right away instead of having to wait for the loop to finish (especially in the case that it yields, which is what happened at one point based on the screenshot for Example #6). I would have suggested to wrap the handleCharacter and setupCharacterAddedConnection function calls with task.spawn(), for reasons that are explained during this video better than I could at 5AM right now (lol), but given how many players can be in the game, it would be creating so many new threads that I’m not sure how much it could impact the game’s performance.


  1. Add a timeout to the character:WaitForChild("Head") call to ensure it doesn’t stop everything else from continuing to run for the remaining Teammates:

To something like this:

local head = character:WaitForChild("Head", 5)

Although you would then need to account for the situation where it times out to ensure the code doesn’t error if it tries to clone the marker into the non-existent part.


There’s a chance that this could be the main culprit of the issue, as at the start of a subsequent match, there was no infinite yield warning on any of my Teammates and I did not end up encountering the nametag issue.


  1. Separate the LocalScript from re-running every time the Character spawns and handle it out of somewhere such as StarterPlayerScripts, instead.

This would be the most drastic change since it would need to be rewritten in a way that would be compatible with listening for a player to swap Teams, among other things to ensure it doesn’t break. However, I imagine that this would make the nametag behavior more predictable since the code would be running at all times, already applying nametags to Teammates that have already spawned as soon as a player chooses a Team, all without needing that player to spawn in themselves.


I hope all of that made enough sense because it is 5 AM here now and I am so incredibly tired haha. If none of those changes affected anything, maybe I’ll continue investigating other possible solutions after I’ve gotten some rest.

1 Like

Wow, just wow. I cannot thank you enough, all of your points are comprehensive and make a lot of sense.

I think this might be the main issue of all, especially wrapping the functions in task.spawn, because until these run, there are no connections set up for new players.

I will update with your suggestions in mind and see how it goes from there. Again, thank you so much for taking the time to go in game, I’ve never seen such support on the forum or anywhere else I’ve posted this issue.

1 Like

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