Improving Touched event

Hi!

I’m trying to script things that you can pick up by walking on top of them. Problem is, the Touched event just isn’t firing a lot of the time. You have to stop moving on top of the item to pick it up, which obviously is a sucky player experience. I want them to be able to just run across it and pick it up.

Any ideas on how to improve the Touched mechanic?

Thanks
-Tom :slight_smile:

function module:New()
    local Coin = ServerStorage.Assets.Coin:Clone()
    Coin.Parent = workspace.CoinsFolder  

    Coin.Touched:Connect(function(Hit)
        -- doesn't fire unless stood still on top of the coin
        local Player = Players:GetPlayerFromCharacter(Hit.Parent)
        if Player then
            Player:IncrementCurrency(1)
            Coin:Destroy()
        end
    end)

    Debris:AddItem(Coin, 30)
end

You should add a debounce to stop the event from firing constantly.

local debounce = false

Coin.Touched:Connect(function(Hit)
    if not debounce then
        debounce = not debounce -- reverses the boolean (sets it to true)
        -- do whatever
    end
end)

Coin.TouchEnded:Connect(function()
    debounce = not debounce -- sets it back to false
end)

That code is pretty obviously example code and doesn’t include all my checks. I have included a denounce and other sanity checks in practice. The issue (and what my question is about) is how to improve the Touched event

I believe size matters with touched events. You could add an invisible part twice the size of the coin and either parent that part to the coin or parent the coin to the part. The event should then fire when the player touches that invisible part. That’s the best I can think of, not sure if there are any other better methods of doing this.

Yeah I agree it’s gotta be something a bit more substantial.

I wish the Touched event was reliable like Unity and Unreal, there’s no collision issues there for size or shape or whatever but Roblox seems to just go mental with it.

1 Like

The touched event should be pretty efficient if you have a debounce in place

I’d also recommend making that invisible part the same height or slightly taller than the player in case the event doesn’t fire.

Well it’s not, that’s the purpose of this post. It doesn’t fire at all unless the player stands still on top of it. It’s a small coin about the diameter or the player’s leg

you could try using a region around the part or add when the player gets close enough to a interactable they have to press a key to interact with it instead of using the touched event

it maybe more work but it would make your game feel more professional and the magnitude between the player and the interactable can be calculated every 0.1 seconds instead of every frame

You should check these out: Proximity Prompts (roblox.com)

That was actually my original implementation but the Project Manager would like it to be touched only (which I personally disagree with).

well i mean the region idea may still work just add a region around the interactable and when a part enters it you can check if its a player. However, you would need to put it in a while loop or use the RunService

Why wouldn’t you weld a Sphere part and check that collision instead of using loops? It’s way way way more efficient and utilises C functions instead of Lua functions

Region3 idea would be a good suggestion. Touched is based on Region3 so you could make your own version of the touched event.

wouldn’t you still need to do constant collision checking with a sphere welded to the interactable?

This might help if the parts have CanCollide set to false.

local function GetTouchingParts(part)

   local connection = part.Touched:Connect(function() end)
   local results = part:GetTouchingParts()
   connection:Disconnect()
   return results
end

local RunService = game:GetService("RunService")

RunService.RenderStepped:Connect(function()
  wait()
  local result = GetTouchingParts(Coin)
  if #result != 0 then
    for i, hit in ipairs(result) do
      if hit.Parent:FindFirstChildWhichIsA("Humanoid") then
          -- do whatever
      end
    end
  end
end)

Constant collision checking being the .Touched connection. Unless you want to constantly run a radius check every so often which is really bad for performance (considering there are 20+ coins at most points when they spawn).