How to detect if the player is touching a part

I dont want to detect if the player has touched a part but if the player is currently touching one is this possible?

5 Likes

Humanoid.Touched Humanoid | Documentation - Roblox Creator Hub

3 Likes

Yes. If you don’t want to use events to detect whether a player is touching a part, you can use BasePart:GetTouchingParts(). The function returns any part that are physically touching the part. If you want to detect parts that are touching geometrically, use WorldRoot:GetPartsInPart() (commonly Workspace). Similar options are available as well if you want to research the WorldRoot methods.

here, something like this should work:

local part: BasePart = script.Parent
local currently_touching = {}

part.Touched:Connect(function(BasePart)
	if game:GetService('Players'):GetPlayerFromCharacter(BasePart.Parent) then
		table.insert(currently_touching, game:GetService('Players'):GetPlayerFromCharacter(BasePart.Parent))
		
		while currently_touching[game:GetService('Players'):GetPlayerFromCharacter(BasePart.Parent)] do task.wait()
			print("Player is still touching.")
		end
		
	end
end)

part.TouchEnded:Connect(function(BasePart)
	if game:GetService('Players'):GetPlayerFromCharacter(BasePart.Parent) then
		table.remove(currently_touching, table.find(currently_touching, game:GetService('Players'):GetPlayerFromCharacter(BasePart.Parent)))
	end
end)
1 Like

Please do not use GetService in a loop, rather define services at the top with global variables.

9 Likes

why is that script not working for me? nothing prints

1 Like

NOTE

Please don’t bump old posts if your reply isn’t helpful to the future readers.

ANSWER

@BarelyFixed’s script should be inside the part that you want to detect touch, but for it to work, you should put it inside every part that you want to detect.

If you want a script that works with every part that the player touches, put this LocalScript below inside StarterPlayer.StarterCharacterScripts:

local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")

local TouchingParts = {} --// The parts that are touching to the character

local RunService = game:GetService("RunService") --// This will be used to print every frame

local function ListenToTouchEnd(hit)
	hit.TouchEnded:Once(function(hit2) --// We use "Once" instead of "Connect" so it ONLY runs the ONCE when hit ends touch (instead of everytime)
		--//-- hit2 = the part that hit ended touch with --//--
		
		if hit2.Parent == Character then --// if hit2's parent is Character then
			while table.find(TouchingParts, hit) do
				table.remove(TouchingParts, table.find(TouchingParts, hit))--// while hit is found in the TouchingParts table, it removes it.
			end
		else
			--// if hit2's parent isn't character then it listens to touch end again
			ListenToTouchEnd(hit)
		end
	end)
end


Humanoid.Touched:Connect(function(hit)
	
	if not table.find(TouchingParts, hit) then --// if it can't find the TouchingPart in the TouchingParts table,
		table.insert(TouchingParts, hit) --// Insert the TouchingPart into the TouchingParts table
		ListenToTouchEnd(hit) --// call the ListenToTouchEnd function
	end
	
	
end)

RunService.RenderStepped:Connect(function() --// This is called every frame
	print(#TouchingParts, TouchingParts) --// Prints the TouchingParts
end)

And this script works best with CanCollide off parts.
It detects all of the parts that are touching to the character.

wait so are you saying that if i want player to be detected player needs to be in part?

The Roblox touch is a one time thing. You can even stand on a touched part and after it fired once it will not fire again until you move. You’ll have to tailor your code around this.

it will sometimes work if the player isn’t in the part

but it will always work if the player is in the part

  • Reason for that is:

because roblox’s BasePart.Touched event works best when a part is inside another part, that’s why you see the kill bricks set to CanCollide false in most obbies.