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
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.
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
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
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).