.touchended triggers randomly (PLEASE HELP)

I am not sure but there’s a possibility it might work. I did something similar when my GUI was not detecting mouseLeave()

1 Like

ZonePlus has different functions, not just detecting players
findPart, findPlayer, getParts etc

1 Like


intresting

script.Parent.Touched:Connect(function(touch)
	if touch.Name == "Box" then
		--touch.Paused.Value = true
		print("ye")
		script.Parent.TouchEnded:Connect(function(touche)
			if touche.Name == "Box" then
				--touche.Paused.Value = false
				print("false")
			end
		end)
	end
end)
1 Like

TouchEnded is also notorious for being faulty and bad

1 Like

yes but get part and find part both needs me to identify the part first, not touching it
I see on item enter but idk, I tried it before and either I did it wrong or it does not work

1 Like

yes but it works perfectly when i delete the script and move it using the workspace mover instead
maybe teleporting isn’t helping the touchended

1 Like

there also is partEnter, you can read up on documentation,


1 Like

Maybe ill use it if it’s the last option possible, I’m running experiments on what could be the cause (Im losing my sanity)

1 Like

okay so after deleting the script, teleporting works, so teleporting isn’t the problem
it legit works fine after i delete the click dector, I think its something in the script

1 Like

You will have to make a check to see if the part is still touching the part you’re checking for if you want to use TouchEnded. Using TouchEnded in this way is going to result in many false-positives.

What Devloper above was trying to say is that you are currently telling the script to run your functions whenever anything touches or stops touching the part area, because you have connected those events to the functions. Therefore, when you or anything else touches it/stops touching it, it will attempt to run those functions, and since “Box” is presently touching the part, it will successfully run them.

Notice how when you are not standing inside of the part it does not repeatedly print “ye” and “false”. That is because when you are standing inside of the part, your player’s idle animation is triggering the event because you are standing inside of the part. The Touched event is not so sophisticated that it can tell whether you are already currently touching the part when checking for touched.

1 Like

intresting, do you have any ideas on checking if it is still touching? since the .touched event is the only thing checking

1 Like

script.Parent.Touched:Connect(function(touch)
	if touch.Name == "Box" then
		--touch.Paused.Value = true
		print("ye")
	end
	script.Parent.TouchEnded:Connect(function(touche)
		if touche.Name == "Box" then
			--touche.Paused.Value = false
			print("false")
		end
	end)
end)

lol

Yeah don’t use that…
I think I used a disconnect there…

1 Like

script.Parent.Touched:Connect(function(touch)
	if touch.Name == "Box" then
		
touch.Parent = script.Parent
			--touch.Paused.Value = true
			print("ye")
		
	end
end)
script.Parent.TouchEnded:Connect(function(touche)
	if touche.Name == "Box" then
		
		if touche.Parent == script.Parent then
			--touche.Paused.Value = false
			print("false")
		end
	end
end)

oh man i really thought this would work for a second there

1 Like

yall i gotta sleep please post your ideas if you have any and ill check it in the morning
cya

1 Like

Make sure that there are no overlapping collisions or unexpected interactions causing the touch event to trigger incorrectly. You might want to review the collision logic and conditions.

If you did check use a hacky trick.
Make a variable called isTouching enable and disable it using the touch and touchendded methods and then just handle the rest with functions.

1 Like

It really depends on the use case, there are alternatives to using touchEnded, but they may not be useful to you depending on what you’re trying to achieve.

But for this, the first thing I would try is go into the function that is connected to touchEnded, and start that function by first checking if the desired part is still touching it by using workspace.GetPartsInPart(yourpart) which will return a table of the parts currently within the bounds of “yourpart”. If the part is still within the part at the time that touchEnded is called, then end, else (if part is not within the table) then [rest of the function].

1 Like

Carried Part Script:

local model = script.Parent.Parent
local prompt = script.Parent
local animation = script.Animation

local distanceZ = -2 -- Model distance from character / how far the model will be from the character
local distanceY = -0.5 -- Model distance from the ground

local animationTrack = nil
local owner = nil
local cooldown = false

prompt.MouseClick:Connect(function(player)
    local character = player.Character
    local humanoid = character:FindFirstChild("Humanoid")

    if not animationTrack then
        animationTrack = humanoid:LoadAnimation(animation)
    end

    if not model:FindFirstChildWhichIsA("WeldConstraint") and owner == nil and humanoid.Health ~= 0 and not cooldown then
        local weld = Instance.new("WeldConstraint", model)

        model.CFrame = character.HumanoidRootPart.CFrame * CFrame.new(0, distanceY, distanceZ)
        weld.Part0 = model
        weld.Part1 = character.HumanoidRootPart
        owner = player.Name
        game.ReplicatedStorage.Events.Placing:FireClient(player, "yep", script.Parent.Parent)
        animationTrack:Play()
        prompt.MaxActivationDistance = 0
        cooldown = true
        wait(2)  -- Cooldown time
        cooldown = false
    end

    humanoid.Died:Connect(function()
        pcall(function()
            animationTrack:Stop()
            model:FindFirstChildWhichIsA("WeldConstraint"):Destroy()

            model.CanCollide = true
            owner = nil
            prompt.MaxActivationDistance = 10
            animationTrack = nil
            model.CFrame = model.CFrame * CFrame.new(0, 0.2, 0)
        end)
    end)
end)

game.ReplicatedStorage.Events.Placing.OnServerEvent:Connect(function(plr, Pos, out)
    if plr.Name == owner then
        animationTrack:Stop()
        model:FindFirstChildWhichIsA("WeldConstraint"):Destroy()

        model.CanCollide = true
        owner = nil

        animationTrack = nil
        model.Velocity = Vector3.new(0, 0, 0)
        model.CFrame = Pos * CFrame.new(0, 0.2, 0)
    end

    prompt.MaxActivationDistance = 10
end)

Handling script:

grabbed = false
db = false
local runservice = game:GetService("RunService")
local circle
local mouse = game.Players.LocalPlayer:GetMouse()
local UIS = game:GetService("UserInputService")
local plr = game.Players.LocalPlayer
local boxe
model = false
rebounce = false
RHeld = false
THeld = false
out = false
local canPlace = true

UIS.InputBegan:Connect(function(key)
    if key.KeyCode == Enum.KeyCode.R then
        RHeld = true
    elseif key.KeyCode == Enum.KeyCode.E and grabbed == true then
        grabbed = false
        if not model then
            game.ReplicatedStorage.Events.Placing:FireServer(boxe.CFrame)
        elseif model then
            game.ReplicatedStorage.Events.Placing:FireServer("Drop")
        end
        circle.Highlight:Destroy()
        circle:Destroy()
    elseif key.KeyCode == Enum.KeyCode.T then
        THeld = true
    end
end)

UIS.InputEnded:Connect(function(key)
    if key.KeyCode == Enum.KeyCode.R then
        RHeld = false
    elseif key.KeyCode == Enum.KeyCode.T then
        THeld = false
    end
end)

game.ReplicatedStorage.Events.Placing.OnClientEvent:Connect(function(yep, box, flat)
    if yep == "yep" then
        grabbed = true
        boxe = box
        circle = boxe:Clone()

        circle.Parent = workspace
        circle.Name = "Circle"
        circle.CanCollide = false
        circle.WeldConstraint:Destroy()
        circle.Anchored = true
        circle.ClickDetector:Destroy()

        local highlight = Instance.new("Highlight", circle)
        circle.CFrame = CFrame.new(Vector3.new(0, 0, 0), Vector3.new(0, 0, 0))
        highlight.FillColor = Color3.fromRGB(0, 237, 1)
        highlight.OutlineColor = Color3.fromRGB(8, 255, 0)
        model = false
        mouse.TargetFilter = circle

        if circle ~= nil then
            circle:Destroy()
        end
    end
end)

mouse.Button1Down:Connect(function()
    if grabbed == true and canPlace then
        canPlace = false
        grabbed = false
        if not out and not model then
            game.ReplicatedStorage.Events.Placing:FireServer(circle.CFrame)
        elseif model and not out then
            game.ReplicatedStorage.Events.Placing:FireServer(circle.Primary.CFrame)
        elseif model and out then
            game.ReplicatedStorage.Events.Placing:FireServer("Drop")
        elseif out and not model then
            game.ReplicatedStorage.Events.Placing:FireServer(boxe.CFrame)
        end

        circle:Destroy()
        wait(2)  -- Cooldown time
        canPlace = true
    end
end)

local target, pos, norm = nil
local bruh = nil

function UpdatePosition()
    local ignoreList = { game.Players.LocalPlayer.Character }
    if circle ~= nil then
        table.insert(ignoreList, circle)
    end
    local mouseRay = mouse.UnitRay
    local newRay = Ray.new(mouseRay.Origin, mouseRay.Direction.Unit * 10000)
    target, pos, norm = workspace:FindPartOnRayWithIgnoreList(newRay, ignoreList)
    bruh = Vector3.new(norm.X, 0, norm.Z)
end

local function Snap(posy)
    PosX = math.floor(mouse.Hit.X / 1 + 0.5) * 1 -- Snaps
    PosZ = math.floor(mouse.Hit.Z / 1 + 0.5) * 1 -- Snaps
end

local function isColliding()
    local isColliding = false

    local touch = circle.PrimaryPart.Touched:Connect(function() end) or circle.Primary.Touched:Connect(function() end)

    local touching = circle.PrimaryPart:GetTouchingParts()

    for i = 1, #touching do
        if (not touching[i]:IsDescendantOf(circle)) and touching[i].Name ~= "White" then
            isColliding = true
            break
        end
    end

    touch:Disconnect()
    return isColliding
end

runservice.Heartbeat:Connect(function()
    if grabbed == true and model == true then
        UpdatePosition()
        Snap()
        local modelSize = circle:IsA("Model") and circle:GetExtentsSize() or circle.Size
        circle:MoveTo(Vector3.new(PosX, -2.75, PosZ) + bruh * (modelSize.X * 0.5))
        local col = isColliding()
        if not col then
            out = false
            circle.Highlight.FillColor = Color3.fromRGB(0, 237, 1)
            circle.Highlight.OutlineColor = Color3.fromRGB(8, 255, 0)
        elseif col then
            out = true
            circle.Highlight.FillColor = Color3.fromRGB(255, 18, 32)
            circle.Highlight.OutlineColor = Color3.fromRGB(255, 70, 47)
        end

        if RHeld == true and not rebounce then
            rebounce = true
            circle:PivotTo(circle:GetPivot() * CFrame.Angles(0, math.rad(90), 0))
            wait(0.5)
            rebounce = false
        end
    end

    if grabbed == true and model == false then
        if (mouse.Hit.Position - plr.Character.HumanoidRootPart.Position).Magnitude < 20 and mouse.Target ~= boxe then
            out = false
        elseif (mouse.Hit.Position - plr.Character.HumanoidRootPart.Position).Magnitude > 20 or mouse.Target == boxe then
            out = true
        end
        UpdatePosition()
        local rotation = circle.CFrame - circle.CFrame.Position
        local endPos = pos + (norm * (circle.Size * 0.5))
        circle.Position = endPos

        if RHeld == true then
            circle.CFrame = circle.CFrame * CFrame.Angles(0, 0.05, 0)
        elseif THeld == true and db == false then
            circle.CFrame = circle.CFrame * CFrame.Angles(math.rad(90), 0, 0)
            wait(1)
            db = false
        end
    elseif grabbed == false and circle ~= nil then
        circle:Destroy()
    end
end)

game.Players.LocalPlayer.Character.Humanoid.Died:Connect(function()
    grabbed = false
    circle.Highlight:Destroy()
    circle:Destroy()
end)

Detecting Script:

script.Parent.Touched:Connect(function(touch)
    if touch.Name == "Box" then
        print("Box touched.")
    end
end)

script.Parent.TouchEnded:Connect(function(touche)
    if touche.Name == "Box" then
        print("Box touch ended.")
    end
end)

Cooldown Mechanism: Added a cooldown variable to prevent rapid reactivation of the box. This ensures that the box cannot be placed again until a cooldown time has passed.

local cooldown = false

Disconnect Input Events: Added proper disconnection of input events when not needed. This helps prevent unexpected behavior, especially when the player dies.

UIS.InputBegan:Disconnect()
UIS.InputEnded:Disconnect()

Cooldown Mechanism: Similar to the carried part script, a canPlace variable was introduced to control when the box can be placed. This prevents rapid placement.

local canPlace = true

These improvements and additions are aimed at making the code more robust, readable, and easier to maintain. The cooldown mechanisms are particularly important to prevent unintended behavior when placing or interacting with the box.

1 Like

It is best for you to not use .Touched and .TouchEnded events as they are very unreliable. Instead use :GetPartsInPart() which is much more reliable.

To use this just do:

local Part = workspace.Part
local function SeeParts()
    for _,part in pairs(workspace:GetPartsInPart(Part)) do
        if part.Name == "Box" then
            print("Touching Box")
            return true
        end
    end
    print("Not touching box")
    return false
end

while Part do
    SeeParts()
    task.wait(1)
end
1 Like

After testing your game with multple solutions I am glad to say My mind is blank…
It seems there’s always a problem detecting with touchended. Why don’t you try region3 or Zoneplus? Seriously man, TouchEnded just feels so broken.

1 Like