Need help with creating a fully working button

I am having an issue with this code, its main objective is to detect people on a button and activate a tween for pressing the button, and unpress the button once no one is on it. The issue that’s arising from this is that if I move around on the button it sometimes does not detect my player being on it, I tried adding a hitbox above the button and using workspace:getpartsinpart but it would also show 0 parts in part sometimes if I kept moving around ontop of the button. Thanks for any help given.

local Tween = game:GetService("TweenService")
local isPressed = false
local plrsPressing = {}

local button = script.Parent
local buttonModel = script.Parent.Parent
local hitbox = buttonModel.Hitbox
local tInfo = TweenInfo.new(0.25, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, false)

hitbox.Touched:Connect(function(player)
	player = player.Parent
	
	if player:FindFirstChildWhichIsA("Humanoid") then -- Check for humanoid to ignore any extra touch events
		if isPressed == false then -- check if the button is unpressed because its now pressed
			isPressed = true 
			table.insert(plrsPressing, player.Name)
			
			local press = Tween:Create(button, tInfo, {Position = Vector3.new(12.375, 0.05, -4.25)}) -- tween for pressing button down
			press:Play()
		end
		
		if isPressed == true and table.find(plrsPressing, player.Name) == nil then -- if the button is pressed but the player is new then it just adds them to the list of players on the button
			table.insert(plrsPressing, player.Name)	
		end
	end
end)

hitbox.TouchEnded:Connect(function(player2)
	player2 = player2.Parent
	
	if player2:FindFirstChildWhichIsA("Humanoid") then
		
		if isPressed == true then
			local tblVal = table.find(plrsPressing, player2.Name)
			
			if tblVal then
				table.remove(plrsPressing, tblVal)
				
				if #plrsPressing == 0 then
					isPressed = false
					local unpress = Tween:Create(button, tInfo, {Position = Vector3.new(12.375, 0.25, -4.25)}) -- put tween for unpress
					unpress:Play()
					
				end
			end
		end
	end
end)

while wait(.2) do -- for value checking
	for i, v in plrsPressing do
		print(v)
	end
	print(isPressed)
end

1 Like

Add a part that is vertically tall on that button, then connect your .Touched events to that part.

2 Likes

if my character is partially outside of the hitbox it the touch ends
like this:

1 Like

In this case you want to use the ZonePlus Module

Your issue is that you are using 2 separate functions to control isPressed.

Since the Touched event happens multiple times with Humanoids and Parts, so does the TouchEnded event.

Your touched event happens and sets isPressed to true with a debounce of 2 seconds and that’s fine but technically you should be setting isPressed to false after the wait(2) (although make it task.wait(2) for better script performance).
The first time the touchended event happens milliseconds after the touched fires it sets isPressed back to false, which means the touched event can get fired again, even though the first touched event is still in the first wait(2).

I just realized i linked the wrong script here’s the actual script that manages the button bruh mb |

local Tween = game:GetService("TweenService")
local isPressed = false
local plrsPressing = {}

local button = script.Parent
local buttonModel = script.Parent.Parent
local hitbox = buttonModel.Hitbox
local tInfo = TweenInfo.new(0.25, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, false)

hitbox.Touched:Connect(function(player)
	player = player.Parent
	
	if player:FindFirstChildWhichIsA("Humanoid") then -- Check for humanoid to ignore any extra touch events
		if isPressed == false then -- check if the button is unpressed because its now pressed
			isPressed = true 
			table.insert(plrsPressing, player.Name)
			
			local press = Tween:Create(button, tInfo, {Position = Vector3.new(12.375, 0.05, -4.25)}) -- tween for pressing button down
			press:Play()
		end
		
		if isPressed == true and table.find(plrsPressing, player.Name) == nil then -- if the button is pressed but the player is new then it just adds them to the list of players on the button
			table.insert(plrsPressing, player.Name)	
		end
	end
end)

hitbox.TouchEnded:Connect(function(player2)
	player2 = player2.Parent
	
	if player2:FindFirstChildWhichIsA("Humanoid") then
		
		if isPressed == true then
			local tblVal = table.find(plrsPressing, player2.Name)
			
			if tblVal then
				table.remove(plrsPressing, tblVal)
				
				if #plrsPressing == 0 then
					isPressed = false
					local unpress = Tween:Create(button, tInfo, {Position = Vector3.new(12.375, 0.25, -4.25)}) -- put tween for unpress
					unpress:Play()
					
				end
			end
		end
	end
end)

while wait(.2) do
	for i, v in plrsPressing do
		print(v)
	end
	print(isPressed)
end
1 Like

You can also use Raycast instead, just check if there’s a player above the button or if the button is under the player

As well as Raycasting (or Shapecasting) you can also use GetPartsInPart.

if i was to check over the player wouldn’t the raycast only check if the players in the middle of the button? also for under the button wouldn’t that require a constant ray shooting from under the player to check constantly if the player goes on a button.

GetPartsInPart has the same issue with sometimes saying 0 parts in part though, maybe I did something wrong?

That’s why the single point raycast should be a shapecast instead if you choose that route.

that would still require a constant ray shooting out though right

Check for only one part of the character

hitbox.Touched:Connect(function(part)
player = game.Players:GetPlayerFromCharacter(part.Parent)
if player ~= nil and part == part.Parent.PrimaryPart then – this checks for the HumanoidRootPart of a player

1 Like

How big is the Part you are using for GetPartsInPart? If you use that you should have a Part the size (x and z) of the button below it, but about 2 or 3 studs high.

When i used GetPartsInPart i created a hitbox about as tall as a regular r6 character, whenever I moved around the value fluctuated sometimes going down to 0

When the characters arms or legs get out of the button area, it is detecting you have left the button.
Just check for the HumanoidRootPart, and nothing more. This will however require a taller hit box

2 Likes

ah I thought of this lol ill try this out

You could check if there are any players at any position between (x,y,z)min and (x,y,z)max. You’d just check if pos.X is bigger than xmin and smaller than xmax. Repeat for y and z. If all are true, there’s a player on top of the button

Thank you, after adding some of these changes to my script it works perfectly now.

1 Like

Ive read about that technique but it seems really out of my range right now lol I’m pretty new to coding