Syntax
-- Validate shape → rate limit → server state → apply actionExamples
Check an action against server state
Create an anchored Part named LessonSwitch in Workspace and a RemoteEvent named ToggleLessonSwitch in ReplicatedStorage. Script in ServerScriptService. Keep the switch anchored so clients cannot move the target through physics ownership.
local Players = game:GetService("Players")
local remote = game:GetService("ReplicatedStorage"):WaitForChild("ToggleLessonSwitch")
local switch = workspace:WaitForChild("LessonSwitch")
assert(switch:IsA("BasePart") and switch.Anchored)
local last = {}
remote.OnServerEvent:Connect(function(player, action)
if typeof(action) ~= "string" or action ~= "toggle" then return end
local now = os.clock()
if now - (last[player] or -math.huge) < 1 then return end
last[player] = now
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
if not root or not root:IsA("BasePart") or not humanoid or humanoid.Health <= 0 then return end
local distance = (root.Position - switch.Position).Magnitude
if distance ~= distance or distance > 12 then return end
switch.Color = if switch.Color == Color3.fromRGB(40, 160, 80)
then Color3.fromRGB(100, 100, 100) else Color3.fromRGB(40, 160, 80)
end)
Players.PlayerRemoving:Connect(function(player) last[player] = nil end)Send intent, not a result
LocalScript in StarterPlayerScripts. Press E near the switch in a Studio play test. The client requests an action; the server decides whether the request is possible. This distance check is not a complete movement anti-cheat system.
local UserInputService = game:GetService("UserInputService")
local remote = game:GetService("ReplicatedStorage"):WaitForChild("ToggleLessonSwitch")
UserInputService.InputBegan:Connect(function(input, processed)
if not processed and input.KeyCode == Enum.KeyCode.E then
remote:FireServer("toggle")
end
end)Best practices
- For numeric input, reject NaN, infinity, out-of-range and fractional values where only integers make sense.
- Check ownership, cooldowns and inventory from server state before granting valuable actions; proximity alone is insufficient.
- Rate limits reduce repeated work but do not make a bad authorization rule safe.
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
RemoteEvent sends a message without waiting for a return value. A client calls FireServer; Roblox supplies the sending Player to OnServerEvent. The server can target one client with FireClient or broadcast with FireAllClients. This example requests a fixed help message, not a reward.Humanoid, HumanoidRootPart and attributes
Humanoid controls character behaviour such as health, while HumanoidRootPart gives a useful spatial reference. Attributes attach small named values to Instances. They are convenient for configuration and display, but client-side attributes are not proof that a player earned a reward.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.RemoteFunction and yielding requests
RemoteFunction is a request/response operation: InvokeServer yields until the server returns. Use it for a small, bounded query when the caller needs a result. Avoid making essential server progress depend on invoking an untrusted client.