How do you get a player from a Touched event?

What I am Trying To Do

Hello! I am trying to make a script the when a player touches a part, the part multiplies the player’s leaderstats. After the player touches it and gets the updated leaderstats, the script disables itself.

Problem

I do not know how to store the player’s name so that the script knows which player it is.

Script

I will assume you want to prevent the player from being awarded the increased multiplier two or more times:

You can make a table and store the player in the table when they touch the part. If the player touches the part, the script will check if the player is in the table or not:

local touched = {} 

function find(player) 
    for _, v in pairs(touched) do
         if v == player then
              return true
         end
    end
end

script.Parent.Touched:Connect(function(hit)
     local player = game.Players:GetPlayerFromCharacter(hit.Parent) 
     if player and not find(player)  then
          table.insert(touched, player) 
          player.leaderstats.NegativeValue.Value = player.leaderstats.NegativeValue.Value * 1.1
     end
end) 
2 Likes

I did that.

would this work
part.Touched:Connect(function(hit)
local player = game:GetService(“Players”):GetPlayerFromCharacter(hit.Parent)
if player then
– do stuff
end
end)

An alternative is to use a dictionary to circumvent the separate find function:

local plyrs = {}
script.Parent.Touched:Connect(function(hit)
    local player = game.Players:GetPlayerFromCharacter(hit.Parent) 
    if player and not plyrs[player] then
        plyrs[player] = true
        player.leaderstats.NegativeValue.Value = player.leaderstats.NegativeValue.Value * 1.1
    end
end)

On another note, sometimes the hit piece is not a direct child of the character, so what I’d sometimes do is (assuming characters are direct children of workspace) repeatedly traverse up the heirarchy until I hit workspace:

while (hit.Parent ~= game.Workspace) do
    hit = hit.Parent
end

Then I would do try :GetPlayerFromCharacter on that piece.

2 Likes

That is the exact script I have.

I understand tables a bit more so I am going to use tables, just so that I can edit it. But thanks for telling me about that!

@Raretendoblox Insert a player’s UserId instead of the actual player object into the tracker table. If you insert a player object into a table, you’ve got a reference to the player. This will cause a memory leak when a player leaves because the table holds a strong reference to the player that is never cleaned.

@Silentude You could probably iterate through all players and check if they have a character, then check if the part is a descendant of that character, over repeated recursion upward which may not provide you with the most accurate results. I don’t assume it’d be much on performance at all, negligibly slower most likely, but definitely better for accuracy.

Thanks! That’s a new way I’ll definitely explore. I do have a question though, from my understanding of recursion, going up the hierarchy in a loop and re-assigning .Parent to hit is not recursion, instead it’s iteration. Am I maybe missing a reason as to why that is considered recursion?

Regarding performance, I agree that either way is negligible. However, I believe my way may actually be more efficient, if my guess of how :IsDescendantOf works. From the wiki, it sounds like the method will check every single branch of children, and their children, and their children’s children, etc. One way I can see this happening, which I believe is how it works under the hood, is recursively, akin to DFS or BFS tree traversals (although there are iterable ways). In addition to that, my method starts from the suspected child right away, and simply goes upwards, so the only worry about it is the depth of the hierarchy while (if my suspicions of :IsDescendantOf are correct) :IsDescendantOf will be affected by the breath and depth of the hierarchy. Lastly, that expensive method then is running for every player’s character, which can expound the issue/ time complexity. A lot of this is speculation though!

-hm this is very interesting I should try it

epic

Recursion and iteration both refer to the concept of repeatedly executing a set of instructions. Recursion calls the same method originally called on one item to another item that is related to it. Iteration is repeated execution of certain instructions until a condition is met. Your code fundamentally displays the concept of upwards recursion but does it through iterations.

IsDescendantOf only checks to see if the passed argument is able to be one of it’s parents. How it’s registered internally I don’t exactly know but I don’t imagine it would be something expensive like unloading the entire hierarchy of the model and finding if the instance the method was called on is part of that unloaded hierarchy. Even then, that would hold a near-zero cost because the engine probably registers this information internally (that a part is a child or descendant of something else).

As for running this on every character, that’s what break is for; to end a loop early should it not need to iterate anymore.

I see, that’s an interesting way to put it. I never labeled a snippet before as recursive when the code itself was iterative, but the concept could be put recursively. “Upwards recursion” is a new concept to me. I tried to google it, but found no information referring to a term like that. In terms of the hierarchy, I can imagine the upwards part.

I’m only setting the .Parent property to the next one, as far as calling a method I cannot find one I am calling during the iteration to (for lack of a better term) “bridge” the iteration to a recursive definition.

This is interesting, I don’t know what that exactly means, but what I was trying to say initially was just a simple tree traversal. I imagine that the part hierarchy can be represented as a bi-directional graph, and my theory of what goes on under the hood is just a simple traversal of said graph, which is found frequently in many algorithms. While it can be expensive, I’m not sure if it’s as expensive as you’re imagining when you use the term “unloading”.

I agree! I would not be surprised if this was the case.

Very true, however with algorithms I like to consider the worst case and the worst case for this is the target character being the last one checked.