I made a kill brick script as I am just getting started in scripting. I have a few problems...
Why does this work perfectly?:
brick = script.Parent function onTouched(hit) if hit.Parent:FindFirstChild("Humanoid") then hit.Parent.Humanoid.Health = 0 end end brick.Touched:Connect(onTouched)
However, this:
brick = script.Parent function onTouched(hit) hit.Parent:FindFirstChild("Humanoid").Health = 0 end brick.Touched:Connect(onTouched)
Outputs an error:
Workspace.Part.Script:4: attempt to index a nil value
Also, when I don't add a ":FindFirstChild":
brick = script.Parent function onTouched(hit) hit.Parent.Humanoid.Health = 0 end brick.Touched:Connect(onTouched)
This outputs the following error:
Humanoid is not a valid member of Workspace
Could someone please explain why this is occurring?
I am also confused as to why while having the error, the script still works perfectly fine, it does the job that I expected
That is because, not only players can touch the brick, but bricks can touch bricks. If you want to change a property of the humanoid of a player when they touch, you first gotta check if the thing that touched the brick really is a player.
brick = script.Parent function onTouched(hit) if hit.Parent:FindFirstChild("Humanoid") then hit.Parent.Humanoid.Health = 0 end end brick.Touched:Connect(onTouched)
Lets decompile the script a little.
The function onTouched runs everytime something touches the brick.
That means if the brick touches the ground it will run the code inside the function.
All player characters in roblox have a humanoid. "hit" is the object that hit the brick.
If the character of a player were to touch the brick, you would do hit.Parent to get to the character because either the legs, arms, torso, head, cosmetics etc. has to touch the brick.
And those objects are a child of the character.
So if my leg touches the brick, we would find the parent of the leg, which is the character. Next that comes up is FindFirstChild.
When you do FindFirstChild, you're trying to find a child of a object that is named what you put inside the brackets. As in the example, FindFirstChild("Humanoid") will try to find an object named "Humanoid".
If FindFirstChild("Humanoid") is not successful of finding an object named "Humanoid", the it will return nil, meaning it is "nothing".
The if statement checks if there is something that is called "Humanoid" inside of the parent of the part.
If there is nothing called "Humanoid", in other words, if its nil, it will not run the code that is inside that if statement, but run past it.
If there is something named "Humanoid", then it will run the code inside the if statement.
So why does the other scripts error?
Thats because you're trying to change the property of an object that does not exist.
As mentioned before, the if statement skips the code inside of it if the object is nil, but if you jump right to hit.Parent:FindFirstChild("Humanoid").Health = 0, then that means you're not checking if the object is existing.
Say the baseplate touches your brick and you write:
hit.Parent:FindFirstChild("Humanoid").Health = 0
Okay, first baseplate, then we go up to workspace and then we try to find an object called "Humanoid" in workspace. Oh, wait! Humanoid is not existing! But why is the player trying to change the health of "Nil"? He should have checked if the object existed before changing the value! And thats when the game complains.
It Says: "I can't change health of something that does not exist!"
I hope this made you undestand a little better why you'll require those extra lines of code. Please call me out if I'm totally wrong of something, if there is something I should add, or if you got more questions.
I guess that's all I have to say.
Happy scripting!
.Touched
is likely firing for other parts touching your part, such as the baseplate. Naturally, the baseplate.Parent
doesn't have a humanoid, so searching for a humanoid in it (hit.Parent:FindFirstChild("Humanoid")
) returns nil
. The "nil value" is Health
, because Health
is not a property of nil
. In short, you're trying to modify a property of nothing.
Your third is breaking because of the same problem (the part touching the baseplate, which doesn't have a humanoid), but demonstrates the difference between :FindFirstChild
and a direct index, hit.Parent.Humanoid
, being that the script will throw an error if you try to directly index something that doesn't exist. So instead of complaining about the "nil value" - the missing property - it's complaining about "Humanoid" not existing in the workspace.
Your first script works because you're only making changes if you're sure whatever you try to index actually exists, by first checking if hit.Parent:FindFirstChild("Humanoid")
before you actually index the humanoid (hit.Parent.Humanoid.Health = 0
).
https://developer.roblox.com/en-us/api-reference/function/Instance/FindFirstChild https://developer.roblox.com/en-us/articles/Nil