Script refuses to resolve player's character

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.")

1 Like

Why don’t you just find the character locally? Also, any server output?

1 Like

I am unable to find the character as localscripts aren’t allowed to get the characters of other players. And as requested, here’s the output:
17:19:18.589 Client: Started installing nametags - Client - TagsCPU:31
17:19:18.590 Client: Installing nametag for FinsterHorizon - Client - TagsCPU:34
17:19:18.590 Client: Requesting character for FinsterHorizon from server. - Client - TagsCPU:70

The server may not be receiving the invoke for some reason, which I’ll check up on very quickly

1 Like

What made you think they can’t? Pretty sure you can get characters from localscripts, but yeah the output looks like the server doesn’t receive anything

Update:
Moved the script to a remotefunction (ik, dumb move) and after reworking some other parts of the system it now works as intended.

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