How can I tell if humanoid.Touched:Connect was hit by another humanoid part?

How can I tell if humanoid.Touched:Connect was hit by another humanoid part?

For example, on the humanoid.Touched event is there a way I can test hit to see if it belongs to another humanoid?

    local character = script.Parent.Parent
    local humanoid = character:WaitForChild("Humanoid")

    local touchedConnection = humanoid.Touched:Connect(function(hit, limb)

    -- How can I tell if hit was any part of a humanoid?

    end)

I tried this but it doesn’t seem to work:

    if hit:findFirstChild("Humanoid") ~= nil then
    	return
    end

Thanks in advance!

2 Likes

Parts don’t have humanoids. Parts are usually in models which the model itself has a humanoid. So do hit.Parent:FindFirstChild("Humanoid").

(also ~= nil is redundant since userdatas are truthy)

It’s not possible for a physical humanoid to trigger that event as it’s not an actual part. However if you wanted to do that to check if a player touched it, you can do:

if game.Players:GetPlayerFromCharacter(Touched.Parent) then

Or generally anything which a model inside you can do:

if Touched.Parent:FindFirstChildOfClass(“Humanoid”) then

2 Likes

I am already inside a humanoid and that definitely is triggered when another humanoid touches me! Maybe it’s because a non-collision script was applied to all humanoid parts?

I’m confused on what issue are you are having?

I’m making something a bit like an obby (not exactly the same). It has lots of challenges. Rather than having an invisible part (like a kill part) per challenge to see if I am out of bounds I am doing it the opposite way around.

I am attaching something inside the character (humanoid.Touched) that monitors everything a human touches and checks to see if it is a good part in the challenge.

This might seem crazy but it’s actually a very low toll on the game because I only need to look at one event and see if the hit part is part of a challenge and tagged as:

challengeStart
challengePart
challengeEnd

If it is challengeStart then I know I can initialize the challenge and if I hit anything other than challengePart or challengeEnd then I failed.

This was working perfectly until I started playing with other players :wink: And they also fire the humanoid.Touched event if I touch them or they run into me.

I have solved this issue with this simple function:

function isHumanoidPart(part)
	
	local humanoidParts = {
	    ["Head"] = true;
	    ["UpperTorso"] = true;
	    ["LowerTorso"] = true;
	    ["LeftUpperArm"] = true;
	    ["LeftLowerArm"] = true;
	    ["LeftHand"] = true;
	    ["RightUpperArm"] = true;
	    ["RightLowerArm"] = true;
	    ["RightHand"] = true;
	    ["LeftUpperLeg"] = true;
	    ["LeftLowerLeg"] = true;
	    ["LeftFoot"] = true;
	    ["RightUpperLeg"] = true;
	    ["RightLowerLeg"] = true;
		["RightFoot"] = true;
		["HumanoidRootPart"] = true;
	}

	if humanoidParts[part.Name] ~= nil then
	    return true
	end
	
end

So, now when the player is in the challenge I can test the incoming humanoid.Touched event hit part and see if it isHumanoidPart(part) and if yes then it just returns because it is not a bad hit.

Hope this makes sense and thanks for your help!

what do you need this for, asking to try to find the best solution for you

I know but what’s the issue you are having with this code?

The issue I was having was that I could not tell if another human triggered my touch event when in a challenge and therefore touching another player triggered that I was out of bounds (even if I was on a valid challenge part).

But I have solved the issue now. Thanks!

Thanks Dan. I want to make it so I can build lots of challenges really quickly and never have to create a kill part.

Why not make it client side then? (Use a local script)

Yes, I do have it as a local script in StarterCharacterScripts. Here is a very simplified version:

local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")
local player = game.Players:FindFirstChild(character.Name).PlayerGui

local isInChallenge = false

local debounce = false

-- create touched connection
local touchedConnection = humanoid.Touched:Connect(function(hit)

	-- make sure this part is valid 
	if isHumanoidPart(hit) or debounce then
		return
	end
	
	debounce = true	
	
	-- If in challenge should we end it?
	if isInChallenge then
		
		if hit:FindFirstChild("ChallengeStart") || hit:FindFirstChild("ChallengePart") then
			
			-- all good
		
		elseif hit:FindFirstChild("ChallengeEnd") then
        
            -- do win stuff

        else
			
            -- do kill stuff		

        end
				
	else
		-- If not in challenge then maybe we should start one
		local challengeStart = hit:FindFirstChild("ChallengeStart")
		if (challengeStart) then
			isInChallenge = true
			-- do start stuff	
		end
	end
	
	wait(.05)

	debounce = false
	
end)

-- disconnect touched connection
humanoid.Died:Connect(function()
	if touchedConnection then
		touchedConnection:Disconnect()
	end
end)

I omitted the isHumanoidPart function declaration because it is above.

To complete it I add a string value to tag the challenge parts. So the string value has a name of ChallengeStart, ChallengePart or ChallengeEnd. It is super easy to copy paste these string values into new challenge and between parts which essentially whitelists the parts and creates the start and end of the challenge.

Now I only need 1 script for all my challenges which means I just have one piece of code to manage and I don’t need scripts on any of the challenge parts.

Taking this one step further. Let’s say I had a complex intricate toxic wall made from 1000 bricks that had a few platforms sticking out that you need to jump up, traditionally I would need to use one of the following methods:

a. Add 1 big invisible part in front of the wall face and if I touch that then it is a kill.
b. Add a kill script to each brick
c. Tag all 1000 blocks using a collection service

With this method I don’t need any of the above I just need to add the string to the platforms with the name challengePart and then it all works. For one challenge not a huge difference but when building a lot of challenges with a lot if intricate parts it can save a lot of time and centralize all the code.

Hope this makes sense!

Ok, so now my game has been out in the wild for a bit and I see that my previous solution above was not good.

It only works for player core parts but if you hit a player accessory or player tool then it does not work.

The thing is I need the function to tell me if I hit anything in the map that belongs to another player (tools, accessories, etc).

So here is a new solution that will tell you if any hit part belongs to another player in the game. Bonus is it’s less code :slight_smile:

function isPlayerPart(part)
	local playerModel = part:FindFirstAncestorOfClass("Model")
	if playerModel and playerModel.PrimaryPart and playerModel.PrimaryPart.Name == "HumanoidRootPart" then
		return true
	end
end

Note: This will break if an accessory contains Models but that seems like a rarity since generally accessories are meshparts. I will post an update if/when I work out how to deal with that rare edge case.

For reference here is my game so you get an idea of why the mechanic is needed:

https://www.roblox.com/games/5893893844/Slider-alpha

1 Like