I created a simple custom nametag for players in my game. The nametag shows a player’s name followed by some stats, which automatically update as the player’s respective leaderstats update. That part works perfectly fine, however, I’ve noticed that the nametag occasionally has issues actually appearing for certain players. For some players it shows perfectly fine, for some it doesn’t, and for some it doesn’t appear on their screens at all while it does for others. The inconsistencies between clients especially confuse me, as nametag ownership is handled through one script in ServerScriptService:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local NameTagTemplate = ReplicatedStorage:WaitForChild("NameTag")
game.Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
local Head = Character:WaitForChild("Head")
local NameTag = NameTagTemplate:Clone()
NameTag.Parent = Head
NameTag.Adornee = Head
NameTag.PlayerName.Text = Player.Name
if Player.Name == "Elliott_RBLX" then
NameTag.PlayerName.TextColor3 = Color3.fromRGB(255, 120, 120)
end
NameTag.DisplayHandler.Disabled = false
end)
end)
This is the entire code. I used WaitForChild() in the event that the script runs before certain essential objects exist, but it didn’t seem to make any difference. The output yields no errors through any server or client and I’m truly at a loss. If anyone could suggest any pointers that might solve this, I’d really appreciate it.
try this script, and if it doesnt work add a debugging print somewhere in the function to see if its working properly.
I think this was just a simple mistake, you put the “end” in the wrong place, but if its still broken thats strange and Ill look into it more.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local NameTagTemplate = ReplicatedStorage:WaitForChild("NameTag")
game.Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
local Head = Character:WaitForChild("Head")
local NameTag = NameTagTemplate:Clone()
NameTag.Parent = Head
NameTag.Adornee = Head
NameTag.PlayerName.Text = Player.Name
if Player.Name == "Elliott_RBLX" then
NameTag.PlayerName.TextColor3 = Color3.fromRGB(255, 120, 120)
NameTag.DisplayHandler.Disabled = false
end
end)
end)
Where would be an ideal place to add a print? The output doesn’t yield any warnings or errors, so I’m assuming the code is at least running all the way through…
Looks like it’s working as expected for me… when I put a print statement in the if statement, it only prints if the player has the username “Elliott_RBLX”. Outside of the if statement, it prints whenever CharacterAdded is fired.
I’ll test it out a bit with the BillboardGUI in ServerStorage instead of ReplicatedStorage, thanks for your time!
Looks like it’s working so far as expected, I have yet to see a nametag fail to load, I’ll test it out a bit more with multiple players before I mark a solution. If anyone knows why storing the player’s nametag in ServerStorage instead of ReplicatedStorage makes a difference, I’d really appreciate an explanation. Thank you again!
Was there any kind of bias or pattern to which players nametags did work and didn’t work?
My only thought is that the GUI wasn’t loaded when the first nametags were created, and they might load faster in Server Storage. Though you did say you were waiting for the important bits, if that included the GUI. Edit: Nevermind I just relooked at the code and saw you were indeed waiting, interesting I’ll keep thinking on it but at least it works now
What does DisplayHandler do? Does it do something as important as making the gui visible?
Is the same nametag instance invisible to one person but visible to another?
If not, maybe this is a problem with the PlayerAdded or CharacterAdded event not firing? You could run through all existing players/characters with the CharacterAdded binding before connecting to PlayerAdded.
Personally, I feel like it would be better to run the nametag logic from a LocalScript, assuming this is for visible updates that only need to be trackable via leaderstats. I think it would remove the consistency problem if bullet 2 was a yes, and it would be easy to set up if you used CollectionService to keep track of all the nametags. That’s a lot of work though, so I would consider this last.
DisplayHandler only updates leaderstat-related text when :GetPropertyChangedSignal() is fired, nothing crucial like visibility.
The same nametag instance is invisible to one person but visible to another, which I believe making the change from ReplicatedStorage to ServerStorage could possibly fix.
According to print statements, the events are indeed firing as intended.
I’ve been testing for about an hour and it seems like the script works flawlessly now, so I think I’m gonna close up this topic. Still not sure what the problem was in the first place but I’m glad it’s fixed now. Thanks, everybody!
Sorry to bump an old thread, but apparently getting the nametags from ServerStorage instead of ReplicatedStorage hasn’t helped at all, as some nametags still don’t appear for some players… once again, no errors in the output and absolutely no consistency to it…
Does anybody else have any suggestions? I feel stuck.
EDIT: Parenting the NameTag to the HumanoidRootPart instead of the Head fixed everything!
Maybe you could try flashing the gui on the client once it gets the nametag.
-- in a local script,
local Players = game:GetService("Players")
local function flashNametag(player)
player.CharacterAdded:Connect(function(character)
local head = character:WaitForChild("Head")
local nametag = head:WaitForChild("NameTag")
nametag.Enabled = false
task.wait(0.03)
nametag.Enabled = true
end)
end
for _, player in ipairs(Players:GetPlayers()) do
flashNametag(player)
end
Players.PlayerAdded:Connect(flashNametag)
It’s definitely a hack, but I’m starting to think it could be a Roblox problem.
It could also reveal if the nametag isn’t being replicated to the clients properly via warning from :WaitForChild, that could be a different test entirely.
Maybe the nametag is getting destroyed, though I heavily doubt it. You could just print the parent on :GetPropertyChangedSignal("Parent") and see if it ever equals nil.