Issue with .Touched and .TouchEnded

Hey there!

This may seem like a game design at first, but I will basically talk about what I want to do:

If the player is in a specific region (an invisible part), it will open the GUI, if the person leaves said region, the GUI will close. It’s just a simple talk one at the moment, however there seems to be an issue with .Touched and .TouchEnded. When I jump, or rapidly leave and enter the part, the GUI starts not working properly. Not sure where to go about this.

Really, it’s a simple script, here it is:

script.Parent.Touched:Connect(function(h)
	local humanoid = h.Parent:FindFirstChild("Humanoid")
	if humanoid then
		game.ReplicatedStorage.Events.Shop:FireClient(game.Players[h.Parent.Name], "open")
	end
end)

script.Parent.TouchEnded:Connect(function(h)
	local humanoid = h.Parent:FindFirstChild("Humanoid")
	if humanoid then
		game.ReplicatedStorage.Events.Shop:FireClient(game.Players[h.Parent.Name], "close")
	end
end)

Video of what’s happening (note when I jump):

3 Likes

.TouchEnded is unreliable. You should check out some other ways to find out if a player is still in a region, like Region3s and GetTouchingParts(). There have been some topics about these where you will find useful info.

6 Likes

Will do some research on it. Could I ask you some questions if I have any? I’ve never used it before.

Also, do you recommend Region3 or :GetTouchingParts more?

2 Likes

If you have any questions that the sources don’t answer, sure. And I would probably look into GetTouchingParts.

2 Likes

Do you recommend a loop to get whether the player is touching it every so often, or do you think .Touched and then :GetTouchingParts in a function would be better? Or something else? I already have a debounce on the other script that tweens the UI so the amount of “requests” sent isn’t really a concern.

1 Like

A method I’ve always used is something like this:

Part.Touched:Connect(function(h)
   if h and h.Parent:FindFirstChild("Humanoid") then
      -- show gui
      repeat wait() until game.Players:GetPlayerFromCharacter(h.Parent):DistanceFromCharacter(part.Position) > 7
      -- hide gui
   end
end

Obviously not the most optimized but it accomplishes the task that it needs to.

TouchEnded has a stigma of being unreliable, seeing as it occasionally fires even if the player is still on the brick. By substituting TouchEnded for a more “reliable” method in DistanceFromCharacter (or a similar .Magnitude method) eliminates the false firing of TouchEnded while keeping the same functionality - it is the best of both worlds.

I would advise against ever relying on TouchEnded for the reasons listed above - it isn’t worth the time and effort it would take to squash any bugs - at least in this scenario.

4 Likes

I’m learning so many new functions I didn’t know existed… I will test this out and update you. Thanks!

Yeah, so I would call GetTouchingParts() on initial touch if that player is the first one within the part, and keep calling it until there are no players in the part anymore. You can do this maybe every .25 seconds
if you wanted to.

Once there are no players in the region, you can break the loop so its not running necessarily, and restart it once a new player touches the part.

Make sure to start this check loop only once until the part is empty again, then break it.

3 Likes

Went with Terry’s solution due to the sheer simplicity, if it does end up causing lag for some reason, I will try using yours next. Thank you for your contribution though, I did some research and I may be able to implement it elsewhere.

There were a few errors, I’ll post the fixed version in case anyone needs this in the future:

script.Parent.Touched:Connect(function(h)
   if h and h.Parent:FindFirstChild("Humanoid") then
      --show
      repeat wait() until game.Players:GetPlayerFromCharacter(h.Parent):DistanceFromCharacter(script.Parent.Position) > 7
      --hide
    end
end)

That’s basically a magnitude check, which will suffice. It’s when you want to find out if something is in a non circular region that Region3 and GetTouchingParts are useful.

1 Like

In this scenario, I wouldn’t rely on the Touched and TouchEnded events, but rather Region3. I recommend checking out @ForeverHD’s Zone+ module, as it may serve as a more reliable alternative.

3 Likes

Ended up trying it and preferred it, it’s much more reliable than doing magnitude checks. Magnitude checks end up having errors anyway. Thanks!

2 Likes