Hello devforum,
I’m doing some much needed upgrades to my nametags system (posted about a month or so ago.) and I’m currently moving it to be clientside, however I’m experiencing some issues.
Because of how this will work, the nametags are located under a ScreenGUI in StarterGUI, and the nametags are supposed to have their .Adornee property set to the head of the player it needs.
Here’s the function from the localscript:
function Buildtags()
local PlayersBuilt = 0
print("Client: Started installing nametags")
for i, CurrentPlayer in Players:GetPlayers() do
print("Client: Installing nametag for " .. CurrentPlayer.Name)
--- VALIDATION ---
local PCName: string = CurrentPlayer:GetAttribute("CharName")
local PCRole: string = CurrentPlayer:GetAttribute("CurrentTeam")
local PCSubr: string = CurrentPlayer:GetAttribute("CurrentSubrole")
-- Validate required attributes exist
if not PCName or not PCRole or not PCSubr then
warn("Client: Missing essential attributes for player " .. CurrentPlayer.Name .. ". Skipping nametag.")
continue
end
local roleData = DataSheet[PCRole] -- Get the main role data using the PCRole key
if not roleData then
warn("Client: DataSheet has no entry for PCRole: '" .. PCRole .. "' for player: " .. CurrentPlayer.Name .. ". Skipping nametag.")
continue
end
local subroleData = roleData.Subroles[PCSubr] -- Get the specific subrole data
if not subroleData then
warn("Client: Role '" .. PCRole .. "' has no entry for PCSubr: '" .. PCSubr .. "' for player: " .. CurrentPlayer.Name .. ". Skipping nametag.")
subroleData = DataSheet.general_crew and DataSheet.general_crew.Subroles and DataSheet.general_crew.Subroles.Cadet
if not subroleData then
warn("Client: Failed to find fallback Cadet subrole. Cannot build nametag for " .. CurrentPlayer.Name)
continue
end
end
local Nametag = TagStore:FindFirstChild(CurrentPlayer.Name) :: BillboardGui
if not Nametag then
Nametag = TagTemplate:Clone()
Nametag.Parent = TagStore
Nametag.Enabled = true
Nametag.Name = CurrentPlayer.Name
-- Call the server to get the character. This will yield until the server returns.
print("Client: Requesting character for " .. CurrentPlayer.Name .. " from server.")
local character = resolveChar:Invoke(CurrentPlayer.Name) -- This MUST return the character!
if not character or not character:FindFirstChild("Head") then
warn("Client: Player " .. CurrentPlayer.Name .. " has no character or head after server lookup, skipping nametag.")
continue -- Skip this player if character isn't available
end
Nametag.Adornee = character:FindFirstChild("Head") -- Now assign Adornee with the received character
if not Nametag.Adornee then
warn("Client: Could not find Head for " .. CurrentPlayer.Name .. " after getting character. Skipping nametag.")
continue
end
else
-- If Nametag already exists, you might want to re-Adornee it if the character has respawned.
-- This is often handled by listening to Player.CharacterAdded event.
-- For simplicity in this `Buildtags` function, we'll assume it's for initial setup.
local character = CurrentPlayer.Character
if character and character:FindFirstChild("Head") then
Nametag.Adornee = character:FindFirstChild("Head")
end
end
-- ... (rest of your nametag property assignments)
local container = Nametag:FindFirstChild("Container")
if not container then warn("Container missing from Nametag for " .. CurrentPlayer.Name); continue end
local texts = container:FindFirstChild("texts")
if not texts then warn("Texts frame missing from Nametag container for " .. CurrentPlayer.Name); continue end
local roleTextLabel = texts:FindFirstChild("Role")
if not roleTextLabel then warn("Role text label missing from Nametag texts for " .. CurrentPlayer.Name); continue end
local charNameTextLabel = texts:FindFirstChild("CharName")
if not charNameTextLabel then warn("CharName text label missing from Nametag texts for " .. CurrentPlayer.Name); continue end
local iconImage = container:FindFirstChild("Icon")
if not iconImage then warn("Icon image missing from Nametag container for " .. CurrentPlayer.Name); continue end
local uiStrokeContainer = container:FindFirstChild("UIStroke")
if not uiStrokeContainer then warn("UIStroke container missing from Nametag container for " .. CurrentPlayer.Name); continue end
local premiumStroke = uiStrokeContainer:FindFirstChild("Premium")
local staffStroke = uiStrokeContainer:FindFirstChild("Staff")
-- Assign Icon
if subroleData.Icon and subroleData.Icon ~= "" then
iconImage.Image = "rbxassetid://" .. tostring(cleanString(subroleData.Icon))
else
iconImage.Image = "rbxassetid://135256916809653" -- fallback placeholder
end
print("Client: Role Name:", roleData.Name)
print("Client: Subrole Name:", subroleData.Name)
-- Assign Text
roleTextLabel.Text = roleData.Name .. ", " .. subroleData.Name
charNameTextLabel.Text = PCName
-- Handle UIStroke (Staff/Premium)
premiumStroke.Enabled = false
staffStroke.Enabled = false
if CurrentPlayer.MembershipType == Enum.MembershipType.Premium then
premiumStroke.Enabled = true
elseif subroleData.Staff then
local isStaff = false
for _, userId in ipairs(subroleData.Staff) do
if userId == CurrentPlayer.UserId then
isStaff = true
break
end
end
if isStaff then
staffStroke.Enabled = true
CurrentPlayer:SetAttribute("isStaff", true)
else
CurrentPlayer:SetAttribute("isStaff", false)
end
else
CurrentPlayer:SetAttribute("isStaff", false)
end
PlayersBuilt += 1
print("Client: Finished nametag for " .. CurrentPlayer.Name)
end
print("Client: Finished nametag installation. Built for " .. tostring(PlayersBuilt) .. " players.")
end
I’m currently using a server script to return the character via a BindableFunction, here’s the OnInvoke function for that:
charResFunc.OnInvoke = function(playerWhoInvoked, targetPlayerName)
print("Server: resolveCharRemote.OnServerInvoke called by " .. playerWhoInvoked.Name .. " for player: " .. targetPlayerName)
local targetPlayer = Players:FindFirstChild(targetPlayerName)
if targetPlayer then
print("Server: Found target player " .. targetPlayer.Name)
local character = targetPlayer.Character or targetPlayer.CharacterAdded:Wait()
if character then
print("Server: Returning character for " .. targetPlayerName)
return character
else
warn("Server: Character not found or not loaded for " .. targetPlayerName)
return nil
end
else
warn("Server: Target player '" .. targetPlayerName .. "' not found.")
return nil
end
end
If anyone is able to help me resolve this issue, please reply here.
To note:
This is for the characters of other players so this isn’t just solved by Players.LocalPlayer.
EDIT: The scripts output stops after the print on line 71, which is print("Client: Requesting character for " .. CurrentPlayer.Name .. " from server.")