🧱 Lua Basics
Variables & Types
Numberlocal x = 42
Stringlocal s = "Hello"
Booleanlocal b = true
Nil (empty)local n = nil
Table (list)local t = {1, 2, 3}
String concat"Hi " .. name
String length#myString
Table length#myTable
Conditions
Equalx == y
Not equalx ~= y
Greater thanx > y
Less or equalx <= y
Andx > 0 and y > 0
Orx == 1 or x == 2
Notnot myBool
If / elseif / elseif … elseif … else … end
Loops
Count upfor i = 1, 10 do … end
Count downfor i = 10, 1, -1 do … end
Loop tablefor i, v in ipairs(t) do … end
While loopwhile condition do … end
Infinite loopwhile true do … end
Break outbreak
Skip stepcontinue
Pause in looptask.wait(1)
Functions & Math
Declarelocal function greet() end
With parameterlocal function add(a, b) end
Return valuereturn a + b
Call itgreet()
Random numbermath.random(1, 6)
Round downmath.floor(3.7)
Round upmath.ceil(3.2)
Format stringstring.format("%02d", 5)
🔧 Common Services
ℹ️
Always use game:GetService("Name") at the top of your script — it's more reliable than game.ServiceName.
Getting Services
Playersgame:GetService("Players")
TweenServicegame:GetService("TweenService")
RunServicegame:GetService("RunService")
DataStoreServicegame:GetService("DataStoreService")
SoundServicegame:GetService("SoundService")
Debrisgame:GetService("Debris")
HttpServicegame:GetService("HttpService")
Players Service
All playersPlayers:GetPlayers()
Local playerPlayers.LocalPlayer
From characterPlayers:GetPlayerFromCharacter(char)
Respawn timePlayers.RespawnTime = 5
Player nameplayer.Name
Player IDplayer.UserId
Player charplayer.Character
TweenService
TweenInfoTweenInfo.new(time, style, dir, reps, rev)
Create tweenTweenService:Create(obj, info, {prop=val})
Playtween:Play()
Easing styleEnum.EasingStyle.Sine
Easing dirEnum.EasingDirection.InOut
Loop foreverrepeats = -1
Ping-pongreverses = true
DataStoreService
Get storeDSS:GetDataStore("StoreName")
Save datastore:SetAsync("key", value)
Load datastore:GetAsync("key")
Update datastore:UpdateAsync("key", fn)
Safe callpcall(function() … end)
Enable in StudioGame Settings → Security → API Services
Events & Connections
Part & Character
Part touchedpart.Touched:Connect(fn)
Stop touchingpart.TouchEnded:Connect(fn)
Click detectorcd.MouseClick:Connect(fn)
Proximity promptprompt.Triggered:Connect(fn)
Humanoid diedhumanoid.Died:Connect(fn)
Health changedhumanoid.HealthChanged:Connect(fn)
MoveTo finishedhumanoid.MoveToFinished:Connect(fn)
Player Events
Player joinedPlayers.PlayerAdded:Connect(fn)
Player leftPlayers.PlayerRemoving:Connect(fn)
Char spawnedplayer.CharacterAdded:Connect(fn)
Char removedplayer.CharacterRemoving:Connect(fn)
Value changedvalue.Changed:Connect(fn)
Attribute changedplayer.AttributeChanged:Connect(fn)
RemoteEvents
CreateInstance.new("RemoteEvent")
Parent toevent.Parent = ReplicatedStorage
Fire one clientevent:FireClient(player, data)
Fire all clientsevent:FireAllClients(data)
Fire serverevent:FireServer(data)
Listen (client)event.OnClientEvent:Connect(fn)
Listen (server)event.OnServerEvent:Connect(fn)
RunService
Every frame (server)RunService.Heartbeat:Connect(fn)
Every frame (client)RunService.RenderStepped:Connect(fn)
Is server?RunService:IsServer()
Is client?RunService:IsClient()
Disconnectlocal c = …:Connect(fn); c:Disconnect()
🏗️ Instances & Properties
Creating & Finding
New instanceInstance.new("Part")
Set parentobj.Parent = workspace
Find childparent:FindFirstChild("Name")
Wait for childparent:WaitForChild("Name")
Find by classparent:FindFirstChildOfClass("Humanoid")
Get childrenparent:GetChildren()
Cloneobj:Clone()
Destroyobj:Destroy()
Part Properties
Positionpart.Position = Vector3.new(0,5,0)
Sizepart.Size = Vector3.new(4,1,4)
Colourpart.BrickColor = BrickColor.new("Red")
Materialpart.Material = Enum.Material.Neon
Anchoredpart.Anchored = true
Can collidepart.CanCollide = false
Transparencypart.Transparency = 0.5
Distance(a.Position - b.Position).Magnitude
Humanoid
Healthhumanoid.Health
Max healthhumanoid.MaxHealth
Kill playerhumanoid.Health = 0
Walk speedhumanoid.WalkSpeed = 16
Jump powerhumanoid.JumpPower = 50
Move to poshumanoid:MoveTo(Vector3)
Root partchar.HumanoidRootPart
Values & Attributes
Set attributeobj:SetAttribute("Name", value)
Get attributeobj:GetAttribute("Name")
Attribute changedobj.AttributeChanged:Connect(fn)
Leaderstatsplayer.leaderstats.Gold.Value
IntValueInstance.new("IntValue")
StringValueInstance.new("StringValue")
Auto-removegame.Debris:AddItem(obj, 3)
📐 Vectors, Positions & GUI Sizes
💡
These trip up almost every beginner. Bookmark this section — you'll come back to it in every episode.
Vector3 — 3D Space
CreateVector3.new(x, y, z)
ZeroVector3.new(0, 0, 0)
Up 10 studsVector3.new(0, 10, 0)
Add vectorsv1 + v2
Scalev * 2
Distance(a - b).Magnitude
Lerp (smooth)a:Lerp(b, 0.1)
Normalisev.Unit
UDim2 — GUI Size & Position
SyntaxUDim2.new(scX, offX, scY, offY)
Full screenUDim2.new(1, 0, 1, 0)
Half widthUDim2.new(0.5, 0, 1, 0)
Fixed 200px wideUDim2.new(0, 200, 0, 50)
Centre positionUDim2.new(0.5, 0, 0.5, 0)
Top-leftUDim2.new(0, 0, 0, 0)
Bottom-rightUDim2.new(1, 0, 1, 0)
AnchorPoint centreVector2.new(0.5, 0.5)
CFrame — Position & Rotation
At positionCFrame.new(x, y, z)
From Vector3CFrame.new(Vector3)
Look at targetCFrame.lookAt(pos, target)
Rotate XCFrame.Angles(math.rad(90),0,0)
Move relativepart.CFrame * CFrame.new(0,5,0)
Get positionpart.CFrame.Position
Lerp (smooth)cf1:Lerp(cf2, 0.1)
Colour & BrickColor
By nameBrickColor.new("Bright red")
RandomBrickColor.random()
From RGBColor3.fromRGB(255, 100, 0)
WhiteColor3.new(1, 1, 1)
BlackColor3.new(0, 0, 0)
Common namesReally red · Lime green · Cyan · White · Black · Gold
Set part colourpart.BrickColor = BrickColor.new("…")
⌨️ Roblox Studio Keyboard Shortcuts
Testing
Play gameF5
Stop gameShift+F5
Pause gameF6
Run (no player)F8
Open OutputView → Output
2-player testTest → Clients and Servers
Transform Tools
Select toolQ
Move toolW
Scale toolR
Rotate toolE
Move cameraRight-click + WASD
Focus on partF (part selected)
Editing
UndoCtrl+Z
RedoCtrl+Y
Copy / PasteCtrl+C / Ctrl+V
DuplicateCtrl+D
DeleteDelete or Backspace
Select allCtrl+A
Save fileCtrl+S
Parts & Groups
Group partsCtrl+G
UngroupCtrl+Shift+G
Toggle anchorAlt+A
Insert PartHome tab → Part
Open ToolboxView → Toolbox
Snap to gridHold Shift while moving
📍 Where Things Go in Explorer
Scripts
Server ScriptServerScriptService
LocalScriptStarterPlayerScripts
LocalScript (char)StarterCharacterScripts
Script in partInside the Part itself
Module scriptReplicatedStorage
GUI & Tools
ScreenGuiStarterGui
BillboardGuiInside the Part
SurfaceGuiInside the Part
Starting toolStarterPack
Tool in worldWorkspace
Tool to give laterServerStorage → clone to Backpack
Shared & Hidden
RemoteEventsReplicatedStorage
BindableEventsServerScriptService
Hidden assetsServerStorage
Shared modulesReplicatedStorage
Lighting effectsLighting (in Explorer)
Sounds (global)Workspace
📋 Ready-to-Use Code Patterns
💡
Hit Copy on any pattern, paste it into your script, then fill in the blanks. The episode tags show where each pattern first appears in the series.
Leaderstats Setup (server) Ep 2Ep 3
local Players = game:GetService("Players") Players.PlayerAdded:Connect(function(player) local ls = Instance.new("Folder") ls.Name = "leaderstats" ls.Parent = player local coins = Instance.new("IntValue") coins.Name = "Coins" coins.Value = 0 coins.Parent = ls end)
Part Touched — get player Ep 1Ep 2Ep 3
part.Touched:Connect(function(hit) local player = game.Players :GetPlayerFromCharacter(hit.Parent) if not player then return end -- do something with player here player.leaderstats.Coins.Value += 1 end)
Moving Platform (TweenService) Ep 1
local TS = game:GetService("TweenService") local info = TweenInfo.new(2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, -1, true) local goal = {Position = platform.Position + Vector3.new(0, 10, 0)} TS:Create(platform, info, goal):Play()
DataStore Save & Load Ep 3Ep 6
local DSS = game:GetService("DataStoreService") local store = DSS:GetDataStore("MyStore") -- Save on PlayerRemoving: pcall(function() store:SetAsync("player_"..player.UserId, {Coins = coins.Value}) end) -- Load on PlayerAdded: local ok, data = pcall(function() return store:GetAsync("player_"..player.UserId) end) if ok and data then coins.Value = data.Coins or 0 end
GUI Label Update (LocalScript) Ep 2Ep 3Ep 4
local player = game.Players.LocalPlayer local coins = player.leaderstats :WaitForChild("Coins") local label = player.PlayerGui .MyGui.Frame.CoinsLabel local function update() label.Text = "🪙 " .. coins.Value end coins.Changed:Connect(update) update()
Chase Nearest Player (Heartbeat) Ep 5Ep 6
local RS = game:GetService("RunService") local Players = game:GetService("Players") RS.Heartbeat:Connect(function() local nearest, minD = nil, math.huge for _, p in ipairs(Players:GetPlayers()) do if p.Character then local d = (npc.Position - p.Character.HumanoidRootPart.Position).Magnitude if d < minD then nearest = p.Character; minD = d end end end if nearest then humanoid:MoveTo(nearest.HumanoidRootPart.Position) end end)
RemoteEvent — server to all clients Ep 4Ep 5Ep 6
-- SERVER SCRIPT: create & fire local RS = game.ReplicatedStorage local evt = Instance.new("RemoteEvent") evt.Name = "MyEvent" evt.Parent = RS evt:FireAllClients("Hello everyone!") -- LOCAL SCRIPT: listen local evt = game.ReplicatedStorage :WaitForChild("MyEvent") evt.OnClientEvent:Connect(function(msg) print("Received:", msg) end)
Kill on Touch + debounce Ep 1
local debounce = {} part.Touched:Connect(function(hit) local hum = hit.Parent:FindFirstChildOfClass("Humanoid") if not hum then return end if debounce[hum] then return end debounce[hum] = true hum.Health = 0 task.wait(1) debounce[hum] = nil end)
🚨 Common Errors & How to Fix Them
⚠️
Always check the Output window (View → Output) when something doesn't work. Errors appear in red and tell you the exact line number.
attempt to index nil value 'leaderstats'
What it means: You're trying to use leaderstats but it doesn't exist yet on that player.
Fix: Make sure PlayerAdded runs before any script tries to read leaderstats. Use player:WaitForChild("leaderstats") in LocalScripts instead of accessing it directly.
attempt to index nil value (local 'player')
What it means: GetPlayerFromCharacter returned nil — the thing that touched the part wasn't a player.
Fix: Always add if not player then return end right after calling GetPlayerFromCharacter. This guards against bullets, NPCs or other parts firing the Touched event.
Infinite yield possible on 'WaitForChild("…")'
What it means: The script is waiting for something that never appears. It will wait forever (and everything below it never runs).
Fix: Check the spelling — it's case-sensitive. Also make sure the thing you're waiting for actually exists and is in the right place in Explorer. Common typo: "leaderstats" vs "LeaderStats".
X is not a valid member of Y
What it means: You're looking for something inside an object that isn't there — wrong parent, wrong name, or it hasn't been created yet.
Fix: Open Explorer and check the exact name and location. Use :WaitForChild() instead of a direct .Name access if the item is created at runtime. Remember names are case-sensitive.
Script timeout: exhausted allowed execution time
What it means: Your script has an infinite loop that never yields — it's hogging all the CPU.
Fix: Any while true do loop must have a task.wait() inside it. Without a wait, Roblox kills the script after a few seconds. Add task.wait(0.1) at the bottom of the loop.
DataStore request was throttled (too many requests)
What it means: You're calling SetAsync or GetAsync too often. Roblox limits how fast you can use DataStores.
Fix: Only save data when the player leaves (PlayerRemoving), not every time a value changes. Wrap all DataStore calls in pcall so a throttle error doesn't crash your script.
LocalScript in ServerScriptService is not allowed
What it means: You put a LocalScript in the wrong place. LocalScripts only run in StarterGui, StarterPlayerScripts, StarterCharacterScripts, or a player's Backpack.
Fix: Move it to StarterPlayerScripts. If you need it to run when the character spawns, put it in StarterCharacterScripts instead.
Unable to cast value to Object
What it means: You passed the wrong type to a function — usually giving a string where an object is expected, or vice versa.
Fix: Check what the function expects. For example, humanoid:MoveTo() needs a Vector3, not a Part. Use part.Position to get the Vector3 out of a part.