Codectionary / Developer documentation / Luau

Touch events, proximity prompts and debounce

Touched reports physical contact and can fire repeatedly for different body parts. ProximityPrompt presents an intentional interaction. Both need server checks for valuable actions, and cooldown state should match the unit you intend to limit: an object, a player or an action.

Syntax

prompt.Triggered:Connect(function(player)
    -- Validate and perform the action on the server.
end)

Examples

Offer a nearby interaction

Create an anchored Part named LessonMarker in Workspace. Script in ServerScriptService adds a prompt. It checks distance and life state again before printing, with a per-player cooldown. This is a demonstration, not a reward system.

local Players = game:GetService("Players")
local marker = workspace:WaitForChild("LessonMarker")
assert(marker:IsA("BasePart") and marker.Anchored)
local prompt = Instance.new("ProximityPrompt")
prompt.ActionText = "Inspect"
prompt.MaxActivationDistance = 10
prompt.Parent = marker
local last = {}
prompt.Triggered:Connect(function(player)
    local character = player.Character
    local root = character and character:FindFirstChild("HumanoidRootPart")
    local humanoid = character and character:FindFirstChildOfClass("Humanoid")
    if not prompt.Enabled or not root or not root:IsA("BasePart") or not humanoid or humanoid.Health <= 0 then return end
    local distance = (root.Position - marker.Position).Magnitude
    if distance ~= distance or distance > 10 then return end
    local now = os.clock()
    if now - (last[player] or -math.huge) < 1 then return end
    last[player] = now
    print(player.Name, "inspected the marker")
end)
Players.PlayerRemoving:Connect(function(player) last[player] = nil end)

Debounce a cosmetic touch reaction

Alternative Script in ServerScriptService for the same anchored LessonMarker. This changes only its color. A single object-wide debounce is appropriate here because the effect belongs to the marker, not an individual player.

local marker = workspace:WaitForChild("LessonMarker")
local busy = false
marker.Touched:Connect(function(otherPart)
    local character = otherPart:FindFirstAncestorOfClass("Model")
    if busy or not character or not character:FindFirstChildOfClass("Humanoid") then return end
    busy = true
    marker.Color = Color3.fromRGB(80, 180, 120)
    task.delay(1, function()
        if marker.Parent then marker.Color = Color3.fromRGB(160, 160, 160) end
        busy = false
    end)
end)

Best practices

  • Use Triggered for a completed prompt interaction and still validate important conditions on the server.
  • A client-side debounce improves presentation but cannot enforce a server cooldown.
  • Reset state on every completion/error path; a flag that stays true can permanently disable an interaction.

At a glance

Purpose
Typed scripting and Roblox development
File extension
.luau
Runs in
Luau host; Roblox engine examples require Roblox Studio
Usually used with
Roblox APIs and Studio

Specifications & further reading

Related Luau documentation