Examples

Short, working scripts. Paste one into a Script inside the part it describes (script.Parent is that part), then change it to suit your game.

Interactive parts

Teleport pad

PlayerTouched fires only for players, so there is no Humanoid check.

local pad = script.Parent
local destination = Vector3.new(0, 100, 0)

pad.PlayerTouched:On(function(player)
    pad.Color = Color3.fromRGB(0, 255, 0)
    player:Teleport(destination)
    task.wait(2)                                   -- handlers may wait
    pad.Color = Color3.fromRGB(255, 255, 255)
end)

Click door

Clicked creates the ClickDetector for you.

local door = script.Parent
local isOpen = false

door.Clicked:On(function(player)
    isOpen = not isOpen
    door:TweenTo({ Transparency = isOpen and 0.7 or 0 }, 0.3)
    door.CanCollide = not isOpen
end)

Laser beam detector

local emitter = script.Parent
local params = RaycastParams.new()
params.FilterDescendantsInstances = {emitter}
params.FilterType = Enum.RaycastFilterType.Exclude

task.every(0.1, function()
    local hit = workspace:Raycast(emitter.Position, emitter.CFrame.LookVector * 100, params)
    if hit then
        local humanoid = hit.Instance.Parent:FindChild("Humanoid")
        if humanoid then humanoid:Damage(50) end
    end
end)

NPCs

Patrolling guard

A rig (Studio: Insert > Humanoid Dummy) walks between two points and rests at each end. See Rigs for every member.

local guard = workspace.Guard.Humanoid
local home = workspace.Guard.Position
local away = home + Vector3.new(20, 0, 0)
local toAway = true

guard.MoveToFinished:On(function()
    task.wait(1)
    toAway = not toAway
    guard:MoveTo(toAway and away or home)
end)
guard:MoveTo(away)

Training dummy

Takes damage from anything that touches it, shows its health in its name, and comes back after five seconds.

local dummy = workspace.Dummy
local humanoid = dummy.Humanoid
humanoid.MaxHealth = 200
humanoid.Health = 200

humanoid.HealthChanged:On(function(health)
    humanoid.DisplayName = "Dummy (" .. math.floor(health) .. ")"
end)
humanoid.Died:On(function()
    task.wait(5)
    humanoid:Respawn()
end)
dummy.PlayerTouched:On(function() humanoid:Damage(10) end)

Animation

Animation player (keyframes on a character)

Limbs can be posed from a script (see Limbs), so a small keyframe player is a few lines. Each pose lists a Transform per limb. The player blends between poses over time and loops. It works on a rig (workspace.Dancer) or on a player's Character.

local character = workspace.Dancer          -- or: player.Character

-- A pose is limb name -> CFrame. A limb that is not listed keeps its current pose.
local animation = {
    { time = 0.0, pose = { RightArm = CFrame.Angles(0, 0, math.rad(60)),  LeftArm = CFrame.Angles(0, 0, math.rad(-60)) } },
    { time = 0.4, pose = { RightArm = CFrame.Angles(0, 0, math.rad(160)), LeftArm = CFrame.Angles(0, 0, math.rad(-160)) } },
    { time = 0.8, pose = { RightArm = CFrame.Angles(0, 0, math.rad(60)),  LeftArm = CFrame.Angles(0, 0, math.rad(-60)) } },
}
local length = animation[#animation].time

local function sample(t)
    for i = 1, #animation - 1 do
        local a, b = animation[i], animation[i + 1]
        if t >= a.time and t <= b.time then
            local k = (t - a.time) / (b.time - a.time)
            for limb, from in pairs(a.pose) do
                local to = b.pose[limb] or from
                character[limb].Transform = from:Lerp(to, k)
            end
            return
        end
    end
end

local t = 0
local connection = RunService.Frame:On(function(dt)
    t = (t + dt) % length
    sample(t)
end)

-- Later: connection:Off() stops it; character:ResetLimbs() gives the limbs back to the animation.

Built-in clips (the Animator)

character.Animator plays the clips Studz ships (Run and Jump) on whichever limbs you pick, with a speed, a weight and fades. See Animations. This turns a rig into a sentry that jogs on the spot while a player is near and stands still when nobody is:

local sentry = workspace.Sentry          -- a Humanoid rig
local animator = sentry.Animator
animator.Locomotion = false              -- it only moves when this script says so

local jog = nil
local function someoneIsNear()
    for _, player in ipairs(Players:List()) do
        local character = player.Character
        if character and (character.HumanoidRootPart.Position - sentry.Position).Magnitude < 30 then
            return true
        end
    end
    return false
end

task.every(0.5, function()
    local near = someoneIsNear()
    if near and not jog then
        jog = animator:Play("Run", { Speed = 1.5, Fade = 0.4 })
        jog.Finished:On(function() jog = nil end)
    elseif not near and jog then
        jog:Stop(0.4)                    -- eases out, then Finished fires with "Stopped"
    end
end)

A clip that does not loop tells you when it is done, which makes one-shot gestures easy to chain:

local animator = player.Character.Animator
local flourish = animator:Play("Jump", { Speed = 0.5, Limbs = "Arms" })
print("the flourish", flourish:Await())      --> the flourish   Ended
animator:Play("Run", { Limbs = "Legs", Weight = 0.5 })

Hat on a head

A part welded to a limb follows it. See Welds.

Players:ForEachPlayer(function(player)
    player:ForEachCharacter(function(character)
        local hat = Instance.Create("Part", {
            Name = "Hat",
            Size = Vector3.new(1.4, 0.8, 1.4),
            Color = "gold",
            CanCollide = false,
            Position = character.Head.Position + Vector3.new(0, 1.1, 0),
            Parent = workspace,
        })
        hat:WeldTo(character.Head)
        character.Humanoid.Died:On(function() hat:Destroy() end)
    end)
end)

Moving platform

A tween that goes up and down forever.

local platform = script.Parent
local info = TweenInfo.new(3, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, -1, true)
TweenService:Create(platform, info, { Position = platform.Position + Vector3.new(0, 20, 0) }):Play()

Day and night cycle

task.every(0.03, function()
    Lighting.ClockTime = (Lighting.ClockTime + 0.1) % 24
end)

Coin spawner

Creates a coin every two seconds, spins it, fades it out and cleans up.

local spawner = script.Parent
local count = 0

task.every(2, function()
    count = count + 1
    local coin = Instance.Create("Part", {
        Name = "Coin_" .. count,
        Position = spawner.Position + Vector3.new(0, 6, 0),
        Size = Vector3.new(1.5, 0.4, 1.5),
        Color = "gold",
        Anchored = false,
        Parent = workspace,
    })
    local spin = coin:Spin(120, "y")
    task.after(5, function()
        coin:TweenTo({ Transparency = 1 }, 1):Await()
        spin:Off()
        coin:Destroy()
    end)
end)

Players

Greet everyone, including who is already here

Players:ForEachPlayer(function(player)
    player:ForEachCharacter(function(character)
        player:Tell("Welcome, " .. player.Name .. "!")
    end)
end)

Collectible coins with automatic saving

The leaderstats folder shows the number in the player list and saves it for you. Every part named Coin gives one coin when touched.

Players.PlayerAdded:On(function(player)
    local stats = Instance.Create("Folder", { Name = "leaderstats", Parent = player })
    Instance.Create("IntValue", { Name = "Coins", Value = 0, Parent = stats })
end)

for _, coin in ipairs(workspace:Descendants()) do
    if coin.Name == "Coin" then
        coin.PlayerTouched:On(function(player)
            player.leaderstats.Coins.Value = player.leaderstats.Coins.Value + 1
            coin:Destroy()
        end)
    end
end

Client and server

Shop remote with validation

local buy = game.ReplicatedStorage:GetChild("Buy")
local prices = { sword = 10, bow = 25 }

buy:Listen({ "string", "integer" }, function(player, item, count)
    local price = prices[item]
    if not price or count < 1 or count > 10 then return end   -- the schema checks types; you check meaning
    -- charge the player, give the item ...
    buy:ToPlayer(player, "bought", item, count)
end)

Events

Wait for a touch, then react once

local trigger = script.Parent

task.spawn(function()
    local hit = trigger.Touched:Wait()        -- parked until someone touches it
    print("Triggered by:", hit.Name)
end)

trigger.Touched:Once(function(hit)            -- Once disconnects itself
    trigger.Material = "Neon"
end)

Watch a property and clean up

local lamp = workspace.Lamp
lamp:GetPropertyChangedSignal("Transparency"):On(function()
    print("lamp is now", lamp.Transparency)
end)
workspace.ChildAdded:On(function(child) print("new object:", child.Name) end)
lamp.Destroying:On(function() print("lamp going away") end)