Log in
Login Sign up Blog Tools

Lua Scripting for Beginners: Write Your First Roblox Script

Scripting is where Roblox games come alive, and it starts smaller than you think: one print, one variable, one part that reacts when a player touches it. This guide takes you from a blank script to three working examples you can paste in and run today.

Lua Scripting for Beginners: Write Your First Roblox Script
In this guide The Three Kinds of Script (And Why Beginners Mix Them Up) Your First Lines: print() and Variables Changing Properties With Code (Example 1: The Makeover Script) Events: Making Parts React (Example 2: The Kill Brick) Putting It Together (Example 3: A Touch Pad That Opens a Door) Reading Errors in the Output Window Common Beginner Mistakes Frequently Asked Questions How long does it take to learn Lua for Roblox? Why does my script do nothing at all — not even an error? What is the difference between FindFirstChild and WaitForChild?

Building makes a game you can look at. Scripting makes a game that does things: doors that open, lava that kills, buttons that give points. Roblox games are scripted in Lua (Roblox's version is called Luau), and the jump from "I can't code" to "my script works" is smaller than people fear. You will learn where scripts live, write your first lines, control parts with code, and finish with three complete working examples — including the famous kill brick. No experience needed.

The Three Kinds of Script (And Why Beginners Mix Them Up)

Half of all beginner scripting problems are not coding problems — they are location problems. Roblox has three script types, and each runs somewhere different:

TypeRuns onPut it inUse it for
ScriptThe server (one copy, for everyone)ServerScriptService, Workspace, or inside a partGame rules: kill bricks, points, doors, data saving
LocalScriptEach player's own device (one copy per player)StarterPlayerScripts, StarterCharacterScripts, inside GUIs (StarterGui), or a ToolOnly that player: camera effects, menus, key presses
ModuleScriptNowhere by itself — a toolbox other scripts borrow with require()ReplicatedStorage (shared) or ServerScriptServiceReusable code and shared data

The rule: anything that affects the whole game — health, points, doors, money — belongs in a Script on the server. A LocalScript changing health on a player's own device will not count, because the server is in charge and does not trust changes made on a player's device (this is called FilteringEnabled). If your script "runs but nothing happens", check type and location before touching a single line of code. This whole guide uses ordinary Scripts.

To create one: in the Explorer, hover over a part (or ServerScriptService), click +, choose Script. Also open the Output window (View tab > Output) and leave it open — it is where your scripts talk back to you.

Your First Lines: print() and Variables

Select all the text in your new script, delete it, and type this. Put the script inside a normal part in Workspace (insert a Part first if you need one):

local part = script.Parent

local message = "Hello from my first script!"
local luckyNumber = 7

print(message)
print("My lucky number is", luckyNumber)
print("This part is called", part.Name)

Press Play. Your three lines appear in Output — that is a running program. What just happened:

  • print() writes text to the Output window. Players never see it; it is your window into what the script is doing. Professionals print constantly while building.
  • local part = script.Parent creates a variable — a named box holding a value. Here it holds the part the script sits inside (script is the script itself; .Parent is whatever contains it). Fetch the part once, then just say part.
  • Variables hold different types: text (a string, in quotes), numbers (7, 2.5) and booleans (true/false). Lua notices capitals: True is not true, Print is not print. Many beginner errors are really capital-letter mistakes.

Changing Properties With Code (Example 1: The Makeover Script)

Everything you can set in the Properties window — colour, size, transparency — a script can set too, while the game runs. Keep the same script inside your part and replace its contents:

local part = script.Parent

part.Color = Color3.fromRGB(0, 170, 255)
part.Material = Enum.Material.Neon
part.Transparency = 0.25
part.CanCollide = false

print(part.Name, "has been restyled!")

Press Play and your part is now glowing blue, slightly see-through, and you can walk straight through it. Details worth knowing:

  • Colours are written as Color3.fromRGB(red, green, blue), each number 0–255 — the same values any colour picker shows.
  • Transparency runs 0 (solid) to 1 (invisible). Trap: a part can be invisible but still solid, because Transparency and CanCollide are separate. Ghost walls and invisible kill bricks combine them on purpose.
  • Materials and other fixed-choice properties use Enum values, like Enum.Material.Neon. Type Enum. and Studio suggests options — use them instead of guessing spellings.

Events: Making Parts React (Example 2: The Kill Brick)

Changing things once, at start, is only half of scripting. The other half is events: "when X happens, do Y". The most-used beginner event is Touched — it fires when something touches a part. Here is the complete kill brick:

local killBrick = script.Parent
local recentlyKilled = {}

local function onTouched(hit)
	local humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
	if humanoid and not recentlyKilled[humanoid] then
		recentlyKilled[humanoid] = true
		humanoid.Health = 0
		task.wait(1)
		recentlyKilled[humanoid] = nil
	end
end

killBrick.Touched:Connect(onTouched)

Read it top to bottom:

  • A function is a named bundle of instructions: local function onTouched(hit) ... end. It does not run when written — it runs when called. hit is the part that touched the brick (usually a character's leg or arm).
  • hit.Parent is the character model the leg belongs to; FindFirstChildOfClass("Humanoid") looks for the Humanoid, which holds health. If a loose part rolls onto the brick there is no Humanoid — and the if stops the script erroring.
  • An if statement runs code only when its condition is true: if humanoid and not recentlyKilled[humanoid] then ... end. Every if ends with end, just like every function.
  • Why the recentlyKilled table? Touched does not fire once per player — it fires for every body part brushing the brick, many times a second. Without this "debounce" guard, one touch runs your code ten times. For health it barely matters (dead is dead), but on a pad giving +10 points per touch, one step would give +200. The debounce remembers "just handled this player", ignores repeats for 1 second, then forgets. Almost every real game script uses this pattern.
  • The last line is the wiring: killBrick.Touched:Connect(onTouched) — "when Touched happens, run onTouched". Forget it and your perfect function never runs.

Putting It Together (Example 3: A Touch Pad That Opens a Door)

Now combine functions, if statements, properties and an event. Build two parts: a floor pad named DoorPad and a wall part named SecretDoor. Put this script inside DoorPad:

local pad = script.Parent
local door = workspace:WaitForChild("SecretDoor")
local busy = false

local function openDoor()
	if busy then
		return
	end
	busy = true

	door.Transparency = 0.7
	door.CanCollide = false

	task.wait(3)

	door.Transparency = 0
	door.CanCollide = true
	busy = false
end

pad.Touched:Connect(openDoor)

Step on the pad: the door fades, lets you through, and closes after 3 seconds. New ideas here: workspace:WaitForChild("SecretDoor") finds another object by name (spelling must match the Explorer exactly); if busy then return end bails out early if the door is already open — the simplest debounce; and task.wait(3) pauses this function without freezing the game. Change the 3 to change the open time. You now know the core of Roblox scripting: variables, properties, functions, if statements, events. Points systems, shops and checkpoints are these same five ideas, arranged bigger.

Reading Errors in the Output Window

Your scripts will error. That is normal — the skill is reading the error. When a script breaks during Play, Output shows a red message like:

Workspace.KillBrick.Script:8: attempt to index nil with 'Health'

It is a full address: where the script is (Workspace > KillBrick > Script), which line (8 — double-click the error and Studio jumps to that line), and what went wrong. The greatest hits:

  • "attempt to index nil with …" — the script tried to use something that does not exist (nil = "nothing"). Usually a wrong name or capitalisation in a FindFirstChild/WaitForChild, or assuming a Humanoid was there. Check spelling in the Explorer.
  • "… expected … near …" — a grammar typo: a missing end, bracket, or then. The reported line is where Lua gave up; the real typo is on that line or just above.
  • "X is not a valid member of Y" — you asked an object for a child or property it does not have. Wrong name, or the object is not where you think in the Explorer.
  • "Infinite yield possible" (yellow warning) — a WaitForChild has waited long for something that may never appear. Translation: name or location is wrong.

Method when stuck: read the line number, look at that line, and print() the values just before it to see what is actually nil. Ninety percent of beginner errors are spelling, capitals, wrong location or a missing end — all findable in two minutes with Output open.

Common Beginner Mistakes

  • Kill logic in a LocalScript. The server ignores health changes from a player's device. Server rules go in a Script.
  • Coding before checking the Explorer. Half of scripting is naming and finding objects. If script.Parent is not what you think, no code can save you.
  • Deleting the ends. Every function and every if needs its own end. The editor's auto-indentation is your clue: if the shape looks wrong, an end is missing.
  • No debounce on Touched. One step becomes twenty events: points explode, doors flicker. Guard touch code from day one.
  • Editing code in Play mode. Those edits apply to the test session only and vanish on Stop. Script in Stop mode; test in Play mode.

Frequently Asked Questions

How long does it take to learn Lua for Roblox?

Useful scripts — kill bricks, opening doors, speed pads — are possible within the first few days, because they all use this guide's five ideas: variables, properties, functions, if statements, events. Designing bigger systems like shops and data saving usually takes a few weeks of small projects. The speed trick: always script for a real game you are building, not in the abstract.

Why does my script do nothing at all — not even an error?

Checklist: is it a Script (not a LocalScript somewhere the server never sees)? Is it somewhere that runs — inside a Workspace part or ServerScriptService? Did you write the :Connect(...) line wiring your function to the event? Does the part's name in your code match the Explorer exactly, capitals included? One of these four is the answer almost every time.

What is the difference between FindFirstChild and WaitForChild?

FindFirstChild("Name") looks once, instantly, and returns the object or nil if it is not there — good for checks like "does this character have a Humanoid?". WaitForChild("Name") pauses the script until the object appears — good for things that must exist, like your door or a player's data folder at join time. WaitForChild when the thing is definitely coming but might be late; FindFirstChild when it might legitimately not exist.

Pawan Nagare
Written by

Pawan Nagare

Rbxmods is a small editorial team focused on sharing helpful Roblox guides, codes, and game tips. We keep things simple, clear, and up to date so players can actually use what they read.

We regularly cover popular games like Blox Fruits, Blade Ball, Pet Simulator 99, and Anime Adventures, along with other trending Roblox titles.

Every guide is based on real gameplay, research, and community feedback to make sure the information is accurate and useful.

Our aim is simple — to help Roblox players get the latest codes, better strategies, and an overall smoother gaming experience..