Touched & TouchEnded Problem

Hello guys! I have a problem with my script (especially with Touched & TouchEnded)
In my script, when the player is in the “Part”, then a Gui does an animation (Tweening) but when the player goes out, the Gui does another animation (2). The problem. When the player goes out, the animation (2) doesn’t work/:

The Script :

local part = script.Parent
local debounce = false

	part.Touched:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" then return end

		plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(0.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true)
	end)

	part.TouchEnded:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" then return end

		plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(1.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true)
	end)

It is true that the touch events in Roblox are unreliable, I had issues myself. Are you doing this in a local or in a server script?

Since you tween a GUI I would suggest this to be done from a local script since you will be checking events only client side. This will be more reliable.

Okay, so I should use a Remot Event?

No need, is that the whole script? I can show you how to transform it into a local script to see if the Touch works better there. Just post the whole script and also where the part is (game.Workspace.Part?).

I put the entire script and part is actually in workspace with the name : Detector

local part = game.Workspace.Detector
local debounce = false

	part.Touched:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" or plr ~= game.Players.LocalPlayer then return end

		plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(0.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true)
	end)

	part.TouchEnded:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" or plr ~= game.Players.LocalPlayer then return end

		plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(1.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true)
	end)

Just put the script somewhere in PlayerGui instead of in the part. Localscripts only activate from PlayerScripts, or PlayerGui (LocalScript | Documentation - Roblox Creator Hub). You can even put it under the ActivateButton.

Try this and see if you have better results.

EDIT: I added a condition to check if the player is the localplayer. You should add it too if you use a localscript because from the client you cannot see the other players’ guis, only yours and this may lead to an error in the script.

I have the same problem ;-;
https://gyazo.com/0b8b0498cf27c59f1d073f553e68e692

hmmmm, can you add some prints like this and then post the video again?

local part = game.Workspace.Detector
local debounce = false

	part.Touched:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" then return end
        print("Touch started")
		plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(0.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true)
	end)

	part.TouchEnded:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" then return end
        print("Touch ended")
		plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(1.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true)
	end)

From what I saw in the Gyazo, it looks like the problem is that the first Tween is still going on when the TouchEnded function starts, so the second Tween never plays. Could you try adding a wait(2) inside the TouchEnded function so that by the time the second Tween starts the first Tween is completed?

1 Like

https://gyazo.com/8e0148facf538aa0ce105205db82d38c

This is a simple fix that could work very well!

Thanks Redridge! gentilmatheo was that gyazo using the code that I suggested?

1 Like

no But I’m trying your code ( wait(2)

By reading the documentation (GuiObject | Documentation - Roblox Creator Hub) it seems that you could check whether the tween will play by using its return value like so:

local part = game.Workspace.Detector
local debounce = false

	part.Touched:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" then return end
		while ~plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(0.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true) do wait(.1) end
	end)

	part.TouchEnded:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" then return end
		while ~plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(1.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true) do wait(.1) end
	end)
1 Like

Why is it you are checking if the part’s name isn’t ‘HumanoidRootPart’? And why are you interacting with GUIs, on the server?

Use “```” (triple backtick. it’s the button over tab) and then another 3 backticks to close.

1 Like

Uhhh little problem with ~
while ~plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(0.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true) do wait(.1) end

Hmm what if you just let the override to true?

local part = game.Workspace.Detector
local debounce = false

	part.Touched:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" then return end
		plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(0.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 1, true)
	end)

	part.TouchEnded:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" then return end
		plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(1.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 1, true)
	end)

Like Redridge said I would recommend using a debounce. When the first Tween starts set the debounce to true and then set it back to false once the tween ends. Then don’t start the second tween until the debounce is false again. Something like this:

local part = game.Workspace.Detector
local debounce = false

	part.Touched:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" then return end
                debounce = true
		local tween = plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(0.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true)
                tween:Play()
                tween.Completed:Wait()
                debounce = false
	end)

	part.TouchEnded:Connect(function(hit)
		local char = hit.Parent
		local plr = game.Players:GetPlayerFromCharacter(char)
		if plr == nil or hit.Name ~= "HumanoidRootPart" then return end
		if debounce == true then
              repeat wait() 
               debounce == false
               until
        end
        plr.PlayerGui.ActivateButton.Bar:TweenPosition(UDim2.new(1.5, 0,0.258, 0),Enum.EasingDirection.Out, Enum.EasingStyle.Linear, true)
	end)

TweenPosition does not return a tween (GuiObject | Documentation - Roblox Creator Hub). However, you can set the debounce in the callback that it accepts as the last argument.

EDIT: Going to sleep, good luck guys!