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)
