How to get all the humanoids in the game, not just players'

I have damage indicators for my game. I’m getting characters through the characteradded event, but that doesn’t work for nonplayer-humanoids. I want to be able to use damage indicators for NPCs as well. How could I get their humanoids?

game.Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		local Hum = char.Humanoid
		local CurrentHealth = Hum.Health
		Hum.HealthChange:Connect(function(Health)
			if Health < CurrentHealth and Hum:GetState() ~= Enum.HumanoidStateType.Dead then
				local Damage = math.floor(CurrentHealth - Health)
				local Indicator = game:GetService("ReplicatedStorage").Assets.Effects.Indicator:Clone()
				Indicator.Parent = game:GetService("Workspace")
				Indicator.Num.TextLabel.Text = tostring(Damage)
				Indicator.CFrame = CFrame.new(char.HumanoidRootPart.CFrame) * CFrame.new(math.random(-2,2), math.random(-2,2), math.random(-2,2))
				coroutine.resume(coroutine.create(function()task.wait(.2)Indicator:Destroy()end))
			end
			CurrentHealth = Hum.Health
		end)
	end)
end)

If anyone could help I would appreciate it!

To define humanoid use WaitForChild()
Like this:

local Hum = char:WaitForChild("Humanoid")

Yep, I’ll change it to that. I guess my question then would be how to get all of the characters in the game, even if it’s not a player.

You should do this instead:

Have a onCharacterAdded() function and use that with PlayerAdded, and then CharacterAdded.

For the NPCs just use the same function. How you can do it is just tag them with CollectionService, use the CollectionService:GetInstanceAddedSignal(tag) event and when an NPC gets added it will run the function on the NPC. Also don’t forget to loop the GetTagged function with your tag just in case anything gets missing (if you use this event once, it shouldn’t). You obviously need to tag all of the NPCs but that should be very easy.

local Characters = {}
for i,v in pairs (game:GetService("Workspace"):GetDescendants()) do
      task.wait()
       if v:FindFirstChild("Humanoid") ~= nil then
          local Char = table.find(Characters,v,1)
          if Char == nil then
               table.insert(Characters,v)
            end
        end
end

Script to define all characters, also if you want to update it when something added then use this script.

local Characters = {}
local function DefineAllCharacters()
table.clear(Characters)
for i,v in pairs (game:GetService("Workspace"):GetDescendants()) do
         task.wait()
       if v:FindFirstChild("Humanoid") ~= nil then
          local Char = table.find(Characters,v,1)
          if Char == nil then
               table.insert(Characters,v)
            end
        end
end
end
DefineAllCharacters()
game:GetService("Workspace").DescendantAdded:Connect(DefineAllCharacters)

Can’t you get all the descendent of workspace then Check if the objects have humanoids and if so add it to a table?

1 Like

I don’t understand what you mean, it’s what this script do.

Ou, I think i know what you mean, not characters, but humanoid, ok, you can.

So when any player joined the game their character is added to workspace and also the NPCs are in workspace, so if you get all the children of workspace (or descendent if you have NPC in folders) you can then check if those objects that you got in workspace (using a for loop) have humanoids and if so add that object to a table

1 Like

This script only checks the models that are the workspace’s children. If the NPCs are placed inside a folder, it will not be able to check them as it will see the “v” as the Folder, not as the NPC model. So :GetDescendants() will work better with your script than :GetChildren()

Though, the NPCs that are supposed to be hit can be grouped into one folder and then that folder can have :GetChildren() ran on it instead. This is better performance-wise

1 Like
local Characters = {}
local Humanoids = {}
local function DefineAllCharacters()
table.clear(Characters)
table.clear(Humanoids)
for i,v in pairs (game:GetService("Workspace"):GetDescendants()) do
         task.wait()
       if v:FindFirstChild("Humanoid") ~= nil then
          local Char = table.find(Characters,v,1)
          local Hum = table.find(Humanoids,v:FindFirstChild("Humanoid"),1)
          if Char == nil and Hum == nil then
               table.insert(Characters,v)
               table.insert(Humanoids,v:FindFirstChild("Humanoid"))
            end
        end
end
end
DefineAllCharacters()
game:GetService("Workspace").DescendantAdded:Connect(DefineAllCharacters)
1 Like

Sorry I just noticed you actually already clear the tables :sweat_smile:

1 Like

Np, thx for advise about performans, you also got error in that i use GetChildren(), i used GetDescendants() already, but i forgot about DescendantAdded and placed ChildAdded event instead(i changed it already).

1 Like

Your use of task.wait() in it drastically slows down your code. As it is going through every descendant of workspace, it is likely that there would be 100s if not 1000s of parts. task.wait() waits 1/60 of a second. Per 600 parts that is 10 seconds of processing time for it, which may be too long for OP’s use case.

You can probably get away with just not having it.

If lag is a concern, there is an optimisation you can try using v:FindFirstChild(“Humanoid”), check if the instance itself is the humanoid (v:IsA(“Humanoid”)). Then replace v with v.Parent later in the script. This just removes the need for the server to loop through each part’s children, which would cause a lot of lag.

2 Likes

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