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