Get the humanoid of a character from ray.Instance if part is nested inside of multiple parts

How can I get the humanoid of a character using ray.Instance if the part that the ray hit is nested inside of multiple parts inside of the character? If I were to cast a ray and I wanted to find the humanoid I could simply use:

local rayCast = workspace:Raycast(Origin, Direction, Params)

if rayCast.Instance.Parent:FindFirstChild("Humanoid") then
-- whatever
end

This would work to a certain degree with the default roblox characters but what if I were to make a custom character and I had multiple parts nested inside of other parts that were also nested inside of other parts? Then to find the humanoid it would get pretty messy:

local rayCast = workspace:Raycast(Origin, Direction, Params)

if rayCast.Instance.Parent:FindFirstChild("Humanoid") or rayCast.Instance.Parent.Parent:FindFirstChild("Humanoid") or rayCast.Instance.Parent.Parent.Parent:FindFirstChild("Humanoid") -- you get it
-- whatever
end

How can I easily write a function that loops through all of the ancestors of the part that was hit by the ray and then if it finds a humanoid inside of ray.Instance.Parent then it returns the humanoid? I’ve been stuck on this for a while and can’t seem to find any information on it.

There are several options, FindFirstAncestorOfClass + FindFirstChildOfClass

local rayCast = workspace:Raycast(Origin, Direction, Params)
if rayCast and rayCast.Instance:FindFirstAncestorOfClass("Model") then
	local Humanoid = rayCast.Instance:FindFirstChildOfClass("Humanoid", true)
	if Humanoid then
		-- Code
	end
end

Parent recursion? I do not recommend it

local rayCast = workspace:Raycast(Origin, Direction, Params)
if not rayCast then				return			end

local HasHumanoid = rayCast.Instance.Parent
if not HasHumanoid:FindFirstChildOfClass("Humanoid") then
    repeat
        HasHumanoid = Parent.Parent
	    if Parent:FindFirstChildOfClass("Humanoid") then
            break
	    end
	    wait()
    until HasHumanoid == workspace
    if not HasHumanoid:FindFirstChildOfClass("Humanoid") then
        print("humanoid not found")
        HasHumanoid = nil
    end
end

and specifically for players

local rayCast = workspace:Raycast(Origin, Direction, Params)
if rayCast then
	for _,Player in pairs(game.Players:GetPlayers()) do
		if Player.Character and rayCast.Instance:IsDescendantOf(Player.Character) then
			print("Found!", Player)
			break
		end
	end
end
9 Likes

The best way to do this 100% accurately is recurse the ancestors to each model and check if there’s a Humanoid child, if there is return that humanoid, if their isn’t find the next ancestor of type model from the current ancestor that you found as model and repeat. This works for parts within models within parts in models of a character if you do that for whatever reason. But it works at any depth with any hierarchy

1 Like