I dont want to detect if the player has touched a part but if the player is currently touching one is this possible?
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)
Please do not use GetService in a loop, rather define services at the top with global variables.
why is that script not working for me? nothing prints
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.