How to make a part turn green when a player is touching it and turn it grey when the player is not touching it

i’m trying to do that when a player touch a part(the part is grey) it’s turn green but when the player step out of the part it return grey.

1 Like

If hit.Parent:FindFirstChild(“Humanoid”) then
Script
end

You can use :GetTouchingParts function for the part and then you can check if there are players touching the part. You will need to use a loop for this.

local Players = game:GetService("Players")
local Part = workspace.Part

local nottouchingcolor = Color3.fromRGB(255, 255, 255)
local touchingcolor = Color3.fromRGB(0, 0, 0)

while task.wait(1) do
    for _, touchingpart in pairs(Part:GetTouchingParts()) do -- :GetTouchingParts() returns a table so we need to loop through to find the player
        if Players:GetPlayerFromCharacter(touchingpart) then --We check if we can find the player from the touching part
            Part.Color = touchingcolor
        else
            Part.Color = nottouchingcolor
        end
    end
end

@mhmdsndb3 If you meant .Touched and .TouchEnded events then those don’t work for what @Antinotin37 asked for. He wants to check if a player is touching it or not. Both of the events only detect when the part got touched and when the touch ended, not if a player is touching the part.

The script might error cause I didn’t test it so let me know when it does, I’ll try to fix it for you.

I have tested this code and it does not detect when the character touches it. I will fix it in a few seconds.

1 Like
local Players = game:GetService("Players")
local Part = workspace.Part

local nottouchingcolor = Color3.fromRGB(255, 255, 255)
local touchingcolor = Color3.fromRGB(0, 0, 0)

while task.wait(1) do
    for _, touchingpart in pairs(Part:GetTouchingParts()) do -- :GetTouchingParts() returns a table so we need to loop through to find the player
        if Players:GetPlayerFromCharacter(touchingpart.Parent) then -- the player's Character , not limb
            Part.Color = touchingcolor
        else
            Part.Color = nottouchingcolor
        end
    end
end

This doesn’t fix anything. I have found out what the problem is, :GetTouchingParts() excludes non-collidable parts. A solution to this would be to use Region3, I’m currently learning about it so I can fix the problem.

By the way, :GetPlayerFromCharacter() also searches for the character by getting the parent of the part so if it was indeed a limb that was touching it, :GetPlayerFromCharacter() would still return the player.

1 Like

Unfortunately I am not able to fix this because I do not have experience working with Region3’s and I need to get off.
I can confirm though that all you need is to create a region and then loop through the parts in that region and check if the part is the character of the player.

I’m a bit late, but .Touched and .TouchEnded will work fine for this.

local part = worksapce.Part
local players = {}

local nottouchingcolor = Color3.fromRGB(255, 255, 255)
local touchingcolor = Color3.fromRGB(0, 0, 0)

part.Touched:Connect(function(hit)
    local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
    
    if plr then
        if not table.find(players, plr) then table.insert(players, plr) end
        part.Color = touchingcolor
    end
end)

part.TouchEnded:Connect(function(hit)
    local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
    
    if plr then
        if table.find(players, plr) then table.remove(players, table.find(players, plr)) end
        if #players == 0 then
            part.Color = nottouchingcolor
        end
    end
end)

Accidentally hit ctrl and enter so sent early lol

2 Likes

He wants to detect if there’s a player touching it or not. He does not want to detect whenever the part is touched or whenever the touch ends. The Region3 way is more accurate and matches exactly what he wants.

I just corrected you by saying that Touched and TouchEnded would work fine, I personally don’t know which would be better, but would think that using Region3 (you would have to check every frame/every few milliseconds) would take up more memory than a simple touched event, which honestly isn’t too inaccurate.

Region3 taking up memory doesn’t matter at all. As I said, Region3 is also much more accurate than the .Touched and .TouchEnded events and there would certainly be delays when using .Touched and .TouchEnded. There are comparisons of .Touch events and Region3 online where you can see how accurate Region3 actually is.

By the way, the reason why Region3 should be needed for this topic is because, let’s say he would use the script you provided. When a player joins, the colour of the part will not change because .TouchEnded only fires when something leaves the part’s area.

What are you even saying? Touched runs every physics update, which handles the part’s color turning green. TouchEnded is to just keep track of players leaving it and will change it to gray/black when there are no players touching the part anymore.

.TouchEnded fires after .Touched because .TouchEnded fires when player leaves the part so how is the part gonna change the colour if the player hasn’t even touched the part?

I’m confused about where you’re getting your logic from. Of course .TouchEnded fires after .Touched, it literally runs when a part leaves the part. .Touched runs each physics update that a part touches the part. Also, this argument is quite useless, I even stated that I was neutral in this position

Both methods of .Touched / .TouchEnded and :GetTouchingParts() will work for this (if you use touching parts, make it connect .Touched with an empty function before using :GetTouchingParts() so it gets anchored parts, jic) You also need to do touchingpart.Parent and not just touchingpart (so it gets the model of the character and not just a part in the character)

That’s what I’m saying, he wants to detect exactly when the player is touching the part and when it isn’t. Region3 will be a very great solution to this because of what I just said.

Well, you can’t do :GetTouchingParts() because character’s body parts are non-collidable so the function will exclude them when collecting the parts, Region3 doesn’t.

Read the update of what I sent, I am neutral in this and never said that a single side was better, I just gave my thoughts about it.

Ending the argument here, not gonna clutter any more than I already have.

For example, with this script it’d be pretty similar, but I would change a few things (script inside of the part):

local Players = game:GetService("Players")
local Part = script.Parent 

local nottouchingcolor = Color3.fromRGB(255, 255, 255)
local touchingcolor = Color3.fromRGB(0, 0, 0)

while task.wait(1) do
    local connection = Part.Touched:Connect(function() end)
    for _, touchingpart in pairs(Part:GetTouchingParts()) do -- :GetTouchingParts() returns a table so we need to loop through to find the player
        if Players:GetPlayerFromCharacter(touchingpart.Parent) then -- the player's Character , not limb
            Part.Color = touchingcolor
        else
            Part.Color = nottouchingcolor
        end
    end
    connection:Disconnect() 
end

Non-collidable still work with :GetTouchingParts()