So basically I have this
local cd = false function onTouched(hit) if cd == false then cd = true game.Players[hit.Parent.Name].leaderstats.Coins.Value = 1 wait(0.3) cd = false end end script.Parent.Touched:connect(onTouched)
The goal of this is that when the part is touched the player's coins turn to 0
but if a accessory touches it rather then the persons body part the script could break
How would I make a fix for this rather then doing
if hit.ClassName == "Part" then
is there a simpler way to do it?
Yes there is another way to do it. It is how you're defining your player.
local canTouch = true local function onTouched(hit) if canTouch then canTouch = false local humanoid = hit.Parent:FindFirstChild("Humanoid") or hit.Parent.Parent:FindFirstChild("Humanoid") if humanoid then local character = humanoid.Parent local player = players:GetPlayerFromCharacter(character) if player then player.leaderstats.Coins.Value = 0 end end wait(0.3) canTouch = true end end
Now you may be asking "Well how exactly does this work?"
First we define the humanoid; we use ternary operators in our favor. In a statement such as a = b or d
it will set a
to which variable has truthiness, if both have truthiness then it is set to d
(If you do not know what truthiness is I suggest looking at this article Truthy, and this Expressions Tutorial)
Now we check if the humanoid actually exists :FindFirstChild()
returns the instance or nil if it does not exist, so if humanoid exists then continue code.
Now we know that the parent of a humanoid will be the player's (or NPC's) physical character model. Having reference to their character allows us to use the :GetPlayerFromCharacter()
method which returns the player that owns that character model. This can be nil
and it will only be nil
if the player is not found. We use :GetPlayerFromCharacter()
and not players[character.Name]
because the humanoid that touched the brick might be a NPC in the game, which have no player instance in the players service.
Finally if the player exists, then index their leaderstats, then their coins, and set the value to 0
Yes, I recommend checking if hit
is a player.
local cd = false function onTouched(hit) local character = hit.Parent local humanoid = character:FindFirstChild("Humanoid") if humanoid then if cd == false then cd = true local player = game.Players:GetPlayerFromCharacter(character) player.leaderstats.Coins.Value = 1 -- or 0 wait(0.3) cd = false end end end script.Parent.Touched:connect(onTouched)
Basically, we're checking for if the part that touched it has something in it called a Humanoid
. If it does, then we know it's a player and we can run the code. If it's not then it won't check through the if humanoid then
statement and pass through.
This way, if an accessory or something else hit it, it wouldn't run the code.
I also made a variable called player, so we can get the player who touched it easier by using GetPlayerFromCharacter
which does what it says :P
I'm a fan of using dictionaries to create player unique debounces, which would look something like this.
local CooldownTime = 10 local Players = game:GetService('Players') local PlayerUniqueCooldown = {} script.Parent.Touched:Connect(function(Part) local Player = Players:GetPlayerFromCharacter(Part.Parent) if not Player then return end if PlayerUniqueCooldown[Player] then return end PlayerUniqueCooldown[Player] = true local Leaderstats = Player:FindFirstChild('leaderstats') if not Leaderstats then return end local Coins = Leaderstats:FindFirstChild('Coins') if not Coins then return end Coins.Value = Coins.Value + 1 wait(CooldownTime) PlayerUniqueCooldown[Player] = nil end)