As a developer, it’s weirdly hard to find the appropriate humanoid that controls a particular basepart.
Consider the problem: A lava brick has been touched, and now I need to figure out what humanoid touched it and deal damage.
The most common solution is to check the parent of the part for a humanoid, then check that parent’s parent and so on until you find a humanoid or run out of parents. This solution works for unaltered characters but it doesn’t work if the humanoid is nestled into a sub-model within its overall character.
The humanoid has a root part, that root part is part of an assembly, and that assembly contains other parts. I want an API that lets me work backwards from the other part to get the humanoid.
Also noting that the naive single hit.Parent solution doesn’t work if an accessory part touches because it’s nested inside an Accessory instance. You’d have to do the recursive search upwards, which I do not care to do for how often I write this code.
part.Touched:Connect(function(hit)
local char = hit:FindFirstAncestorOfClass("Model")
local hum = char:FindFirstChildOfClass("Humanoid")
if hum then
-- code
end
end)
part.Touched:Connect(function(Object)
while not Object:FindFirstChildOfClass("Humanoid") and Object ~= workspace do
Object = Object.Parent
end
local Human = Object.Parent:FindFirstChildOfClass("Humanoid")
if Human then
-- code
end
end)
part.Touched:Connect(function(Object)
while not Object:FindFirstChildOfClass("Humanoid") and Object ~= workspace do
Object = Object:FindFirstAncestorOfClass"Model" -- FindFirstAncestorOffClass does less work sometimes.
end
local Human = Object.Parent:FindFirstChildOfClass("Humanoid")
if Human then
-- code
end
end)
Hit.Parent is one of the most annoying things developers decide to use when making kill bricks. Just create a custom hitbox. Unless you use R6, then it’s a little more understandable
Sharksie has been a developer for an extremely long time, they know how to do this manually. They’re saying it’s too annoying, not impossible. I think this is a good idea.
But we don’t have dedicated API for looking on the same plane of hierarchy. Now it’s not too difficult to make these as custom functions, plus FindFirstChild & FindFirstDescendant do look at the entire plane before going down, however FindFirstAncestor doesn’t when going up.
A potential feature request could be to have the following:
A way to look on the current plane of hiearchy: Instance:FindFirstSibling()
A way to look up recursively and check the entire plane: Either a change to Instance:FindFirstAncestor() (May break current scripts), or Instance:FindFirstRelative()
This would include all the extra versions such as OfClass, WhichIsA, Is...Of and the associated Added & Removed / Removing events.
Since I mentioned custom functions before, here’s some for the Sibling series:
-- Simply grabs the parent and uses the Child functions --
local function FindFirstSibling(object: Instance, name: string): Instance?
local parent = object.Parent
return (parent and parent:FindFirstChild(name))
end
local function FindFirstSiblingOfClass(object: Instance, class: string): Instance?
local parent = object.Parent
return (parent and parent:FindFirstChildOfClass(class))
end
local function FindFirstSiblingWhichIsA(object: Instance, className: string): Instance?
local parent = object.Parent
return (parent and parent:FindFirstChildWhichIsA(className))
end
local function GetSiblings(object: Instance): {Instance}
local parent = object.Parent
return (parent and parent:GetChildren())
end
local function IsSiblingOf(object: Instance, sibling: Instance): boolean
return (object.Parent == sibling.Parent)
end
local function SiblingAdded_Connect(object: Instance, func: (child: Instance) -> ()): RBXScriptConnection? -- Along with Once, Wait & ConnectParallel --
local parent = object.Parent
local connection: RBXScriptConnection?
if parent then
connection = parent.ChildAdded:Connect(func)
end
return connection
end
local function SiblingRemoved_Connect(object: Instance, func: (child: Instance) -> ()): RBXScriptConnection? -- Along with Once, Wait & ConnectParallel --
local parent = object.Parent
local connection: RBXScriptConnection?
if parent then
connection = parent.ChildRemoved:Connect(func)
end
return connection
end