Issue with Touched event distance check

I want to detect the precise distance of a player whenever they trigger a Touched event.

For example, when this event is fired on a button, I’d like to check whether it is actually possible for the player to do so from where they’re at.

This is because cheaters can trigger Touched events themselves even if they are all the way on the other side of the map.

My current solution to prevent this is by adding a distance check to the Touched event handler. Like this:

local button = workspace.ButtonBlock

button.Touched:Connect(function(part)
    if (part.Position - button.Position).Magnitude < 15 then
        -- Do whatever.
    end
end

However, Roblox’s physics tweening is throwing in a wrench here, because the Touched event fires before the player’s character physically reaches the button, this results in really large distances from players legitimately falling on top of the button, and forces me to increase the maximum interaction distance significantly to compensate.

Here’s a video of the problem where I fall really fast on a blue pad, and then get distance-checked.

TouchLagRepro.rbxl (28.7 KB)

2 Likes

How about try adding a wait before even checking the distance?

4 Likes

That may work, though I then need to know how long it would take before the player’s physical character is tweened onto whatever I’m checking after the Touched event is fired, otherwise I’d still have the same problem.

My best guess right now is one-fifth of a second.

2 Likes

You should start with 1 fifth until you get the perfect timing :slight_smile: try multiple numbers

1 Like

It seems that 1/6th of a second works best.

I really do hate doing it this way. Oh well. Ugly hacks everywhere, but it works.

I’m gonna leave topic this open for a while in case other people have ideas.

Thanks.

2 Likes

You know what, this got me thinking.

I could repeatedly check the distance over a fraction of a second, so that the player triggers the button as soon as they are physically close enough. This means I won’t have to delay the server’s reaction except to the extent that the player remains too far away!

It’s even uglier, but something like this would work regardless of how much players are tweened, and the artificial wait is reduced whenever the situation permits.

local RunService = game:GetService("RunService")

button.Touched:Connect(function(part)
    local isCloseEnough = false
    for i = 1, 30 do
        -- It's possible this will be true on the first try and there will
        -- be no waiting at all.
        isCloseEnough = (part.Position - button.Position).Magnitude < 15
        if isCloseEnough then
            break
        end
        -- 1/60th of a second, using RunService to avoid clogging the
        -- task scheduler with spammed wait commands.
        RunService.Heartbeat:Wait()
    end
    if isCloseEnough then
        -- Do whatever.
    end
end
3 Likes

I am not at home, but i believe there is a character state that can be check called “IsFalling” or freefall or something like that. If that is true then you can wait til’ it is false you should know that the server has caught up. Just a thought!

1 Like