Effecient Alternative to TouchEnded()?

Hello, I’m working on this button system that involves 2 player simultaneously stepping on 2 separate buttons to activate. I want the buttons to be active while the player is standing on them, and de-activate if a player steps off.

My Approach:

My first thought was to use TouchEnded(), when the touch event is fired it sets a BoolValue Object to true, to represent that the button is currently active. Here is the code for that:

button1.Button.Touched:Connect(function(hitObj)
	if hitObj.Parent:FindFirstChild("Humanoid") then
		if activated1.Value == false then
			activated1.Value = true -- these 'activated' variables contain BoolValues for both of the buttons in the system
		elseif activated1.Value == true and activated2.Value == true then
			openDoor()
		end
	end
end)

button1.Button.TouchEnded:Connect(function(hitObj)
	if hitObj.Parent:FindFirstChild("Humanoid") then
		if activated1.Value == true then
			activated1.Value = false
		end
	end
end)

My issue: With Roblox’s default TouchEnded() event, it seems to glitch. When the player moves on the button, it ‘flickers’ the BoolValue (switches between true and false). It is possible for the player to stop moving on the button and it will stay activated. But of course, its inefficient to have the player stop on it. (and it doesn’t work 100% of the time).

GIF:
a90b0c32910aa69798ccf1ff40ca1eda

What I’m looking for: Either a fix to my code (could be user error lol) or a different method / approach to this? I want the player to be able to stand on it and move around the button and until they step off/away from the button it should stay activated.

There’s a different method to this. The button can be touched by multiple parts at once, and the TouchEnded may be firing for a foot that did get off while there is a foot that is still on the button. What you want to do is this:

local TouchingTable = {}
local Part = workspace.Part -- or whatever the button is

Part.Touched:Connect(function(Object)
    if Object.Parent:FindFirstChild("Humanoid") then
        local Character = Object.Parent
        if not table.find(TouchingTable, Object) then
            table.insert(TouchingTable, Object)
            -- put activation code here (remember this fires every time a new character part steps on this button)
        end
    end
end)

Part.TouchEnded:Connect(function(Object)
    if Object.Parent:FindFirstChild("Humanoid") then
        if table.find(TouchingTable, Object) then
            table.remove(TouchingTable, table.find(TouchingTable, Object))
        end
        if #TouchingTable == 0 then
            -- deactivate because there aren't any characters touching the button
        end
    end
end)
14 Likes

Thanks so much! This is such a smart approach. Hopefully I’ll be able to implement this for multiple buttons. Thanks :smiley: :heart:

2 Likes

Of course, glad I could help! :smirk_cat:

Hey, the best alternative to TouchEnded is using ZonePlus:

Let me know if you need help!