Search code examples
luaroblox

Tag a player who touches script.Parent


So I want this to tag a player, however it just does nothing!

local playersTouching = {}

local function onPartTouched(part, player)
    if part == script.Parent and player and player:IsA("Player") then
        player:SetAttribute("Hiding", true)
        playersTouching[player] = true
    end
end

local function onPartTouchEnded(part, player)
    if part == script.Parent and player and player:IsA("Player") then
        player:SetAttribute("Hiding", nil)
        playersTouching[player] = nil
    end
end

script.Parent.Touched:Connect(function(otherPart)
    local humanoid = otherPart.Parent:FindFirstChildOfClass("Humanoid")
    if humanoid then
        onPartTouched(script.Parent, humanoid.Parent)
    end
end)

script.Parent.TouchEnded:Connect(function(otherPart)
    local humanoid = otherPart.Parent:FindFirstChildOfClass("Humanoid")
    if humanoid then
        onPartTouchEnded(script.Parent, humanoid.Parent)
    end
end)

So I run this on Roblox, and the Player touches the script.Parent, but the player doesn't get tagged. The goal of this is to detect when the player is touching otherPart along with script.Parent. If my method doesnt work please suggest another method. Thx!

AMENDMENT: Now my detection script ain't working. So is it the same issue where I am getting the character instead of the player?:

script.Parent.Touched:Connect(function(player)
    print("TOUCHED")
    if player:GetAttribute("Hiding") then
        print("tag player touch????")
    else
        print("HMM")

    end
end)

Solution

  • You are making the simple mistake of confusing a Player object with their character model that runs around the Workspace. They both have the same name, but are different classes.

    Looking at these lines :

    onPartTouched(script.Parent, humanoid.Parent)
    
    -- which calls ... 
    
    local function onPartTouched(part, player)
        if part == script.Parent and player and player:IsA("Player") then
    

    You are checking if the player variable IsA("Player"), but this check will always be false because the humanoid.Parent is a Model, not a Player.

    A better way to get the Player is to use Players:GetPlayerFromCharacter(). And something to be careful about when it comes to the Touched and TouchEnded signals is that your character model can fire the signal multiple times. So to make sure that the code only fires once you completely stop touching the part, it's a good idea to keep count of how many parts or touching the block. Check out this answer for more details.

    So try this :

    local Players = game:GetService("Players")
    local playersTouching = {} -- <Player, int>
    
    script.Parent.Touched:Connect(function(otherPart)
        local player = Players:GetPlayerFromCharacter(otherPart.Parent)
        if player then
            -- only set the attribute once
            if not playersTouching[player] then
                playersTouching[player] = 0
    
                -- do the thing for the first time
                player:SetAttribute("Hiding", true)
                print(player.Name .. " is now hiding")
            end
    
            -- keep count of the number of objects touching the block
            playersTouching[player] += 1
        end
    end)
    
    script.Parent.TouchEnded:Connect(function(otherPart)
        local player = Players:GetPlayerFromCharacter(otherPart.Parent)
        if player then
            -- decrement the counter
            playersTouching[player] -= 1
    
            -- only remove the attribute once all the touching pieces have stopped
            if playersTouching[player] == 0 then
                playersTouching[player] = nil
          
                -- do the thing that happens only once
                player:SetAttribute("Hiding", nil)
                print(player.Name .. " is no longer hiding")
            end
        end
    end)