Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Touched event firing multiple times for one part?

Asked by 5 years ago

I'm having trouble with the Touched event. Essentially I'm trying to make interact-able (?) shops. When the player touches an invisible part the script displays a prompt ("Press E to interact"). When the player presses E it then displays the shop GUI.

The prompt should obviously disappear once the player has pressed E and it should un-queue the E key from ContextActionService, however it appears this isn't happening every time - sometimes if you press E the prompt will stay on screen and then disappears when you press E a second time.

I added a couple of print()s with timestamps and it looks like the Touched event is being fired multiple times (particularly when walking through the invisible part) causing the PROMPT.SHOW() function to run multiple times as well.

Is there a fix for this or am I better moving away from the Touched event altogether? If so what is the best/most efficient alternative? Code is below, thanks

local INPUT = game:GetService("ContextActionService")

local PLAYER = game:GetService("Players").LocalPlayer
local CHARACTER = PLAYER.Character
local TORSO = CHARACTER:WaitForChild("HumanoidRootPart")

local ALL_SHOPS = game.Workspace:WaitForChild("Shops")

local TOUCHING = nil

local function OPEN_SHOP(_, STATE)
    if STATE == Enum.UserInputState.Begin then
        INPUT:UnbindAction("OpenShop")
        local HUMANOID = CHARACTER:WaitForChild("Humanoid")
        local LAST_WALKSPEED = HUMANOID.WalkSpeed
        HUMANOID.WalkSpeed = 0
        HUMANOID:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
        script.Parent.Prompt.Visible = false

        local UI = script.Parent.Frame
        UI.ExitBtn.MouseButton1Down:Connect(function()
            UI.Visible = false
            if TOUCHING ~= nil then
                INPUT:BindAction("OpenShop", OPEN_SHOP, false, Enum.KeyCode.E)
                script.Parent.Prompt.Visible = true
            end
            HUMANOID.WalkSpeed = LAST_WALKSPEED
            HUMANOID:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
        end)
        UI.ScrollingFrame:ClearAllChildren()
        UI.TotalTxt.Text = "Total: £0.00"
        UI.ShopNameTxt.Text = TOUCHING.Parent.Name
        local ITEMS = require(TOUCHING.ModuleScript)
        for i, details in pairs(ITEMS) do
            local FRAME = script.ItemFrame:Clone()
            FRAME.Position = UDim2.new(0, 0, 0, FRAME.Size.Y.Offset * (i - 1))
            FRAME.ImageLabel.Image = details[2] or FRAME.ImageLabel.Image
            FRAME.ItemTxt.Text = "£"..tostring(math.floor(details[3] * 100) / 100).." "..details[1]
            FRAME.Parent = UI.ScrollingFrame
        end
        UI.Visible = true
    end
end
local PROMPT = {
    SHOW = function()
        print("Showed prompt @ "..os.time())
        INPUT:BindAction("OpenShop", OPEN_SHOP, false, Enum.KeyCode.E)
        script.Parent.Prompt.Visible = true
    end,
    HIDE = function()
        INPUT:UnbindAction("OpenShop")
        script.Parent.Prompt.Visible = false
    end,
}

TORSO.Touched:Connect(function(newPart)
    print("Touched new part: "..newPart.Name)
    if newPart:IsDescendantOf(ALL_SHOPS) and TOUCHING == nil then
        TOUCHING = newPart
        PROMPT.SHOW()
    end
end)
TORSO.TouchEnded:Connect(function(oldPart)
    if oldPart == TOUCHING then
        TOUCHING = nil
        PROMPT.HIDE()
    end
end)
0
add a debounce here is a vid on how to use debounce if u dont know already: https://www.youtube.com/watch?v=HoZkuvd6RPA&t=0s Gameplayer365247v2 1055 — 5y

1 answer

Log in to vote
1
Answered by 5 years ago

Answered on Discord, thanks to NewVoids. I added another print() to the TouchEnded event which it turns out was also firing which was setting TOUCHING to nil which is why the Touched event wasn't stopped by the if statement checking if TOUCHING == nil.

It's not a solution as such but as a workaround rather than just doingif oldPart == TOUCHING then I instead used GetTouchingParts(), looped through all the parts touching the HumanoidRootPart, and if it included the invisible shop part I return'd to terminate the function. Entire script is the same save for this last bit:

TORSO.TouchEnded:Connect(function()
    for _, part in pairs(TORSO:GetTouchingParts()) do
        if part == TOUCHING then return end
    end
    -- From here on won't run if the torso is still touching the invisible shop part!
    TOUCHING = nil
    PROMPT.HIDE()
end)
0
put "[Solved]" in the title Fad99 286 — 5y
Ad

Answer this question