Scripting Basics - Beginner guide to lua and Roblox

Hello! :smile:
I’ve written this guide/tutorial to help people who are new to scripting on Roblox learn some basic concepts of scripting, and hopefully understand it better. This is definitely missing a lot of important information, but I will be updating it more in the future!

If you’re brand new you should read The Basics below, but if you know about variables, functions, and data types you should skip to Concepts, where I explain some of the Roblox-specific ideas that’ll allow you to read the information on the devhub (https://developer.roblox.com)

The Basics

Data types

Strings

Strings hold text! They are surrounded by double quotes, ", or single quotes, '. They can also be surrounded with [[ and ]] to make them span across multiple lines, which is usually called a “multi-line” string.

Tables

Tables hold data. You may have heard of arrays which are lists, or dictionaries which “map” a specific thing to another. Dictionaries are sometimes referred to as objects, like in JavaScript. Tables work as an array or a dictionary, and can even work as both at once.

{"My array", "is cool"} -- Like a dictionary, but the indexes are numbers in order, and there are no gaps.
{["My object"] = "is cool"} -- Can have indexes with any value, even other dictionaries. It can be an array too.

Booleans

Booleans are either true or false, yes or no. They aren’t much, but they offer a lot of use in programming. When you compare values in programming languages you’ll get a boolean.

1 < 3 -- One is less than three, so true
4 == 2 -- Four doesn't equal two, so false
6 > 7 -- 6 is less than 7, not greater than, so false again

Numbers

Numbers, 1, 2, 3, and anything else. In a lot of other programming languages numbers can either be an integer (a whole number), or a float/double (which store numbers with decimals, kind of like scientific notation).

Lua numbers can contain decimals. You can use fractions too, by dividing: 1/5 = 0.2

Variables and functions

Variables are simply a way to store a single thing in them. They can hold anything, and are one of the most important features in all programming languages. In lua they can be local, meaning they can be used where they are created, or global meaning they can be used anywhere.

variable = "My string" -- A global
local localVariable = "My other string" -- A local

do -- I don't do anything special, but I have my own set of locals, which is called a scope.
	print(abc) -- I can't see the variable yet, so I access a global, but since there is no global named that I will print "nil" which means no value. It's sort of like "null" in other programming languages.
	local abc = 123 -- I only exist inside of my scope, under this do statement, and I can be used by future code
	-- Everything past here can see the abc local now:
	print(abc) -- prints 123
end
print(abc) -- I can't see the abc local, since its in a different scope, so I use the global abc, which is nil still.

Functions can run the same code multiple times. Functions can be local too, and are just a type of value.

local function myFunction(a, b, c) -- These are like local variables. They're called arguments, and they can be given to the function when you "call" it
	return a, b, c
end

print(myFunction(1, 2, 3)) -- This calls the function and gives it 1, 2, and 3 as its arguments. This calls `print(1, 2, 3)` because myFunction returns all three numbers.

local myFunction2(a, b, ...) -- ... Is like a variable but can only be created inside of a function's arguments. It represents multiple values at once
	print(a, b) -- This will print the first two arguments
	warn(...) -- But this will warn any other arguments
end

myFunction2(1, "b", 2, "d", 3, "f")

Statements

Statements make up code.
There are different types of statements.
For example, the if statement, which executes code, if a condition is true. If statements use booleans!

if true then
    print("It ran!")
end

if false then
    print("You won't see me because the condition is false!")
end

Remember nil? Nil acts like false in an if statement. And all other values act like true.

if nil then
    print("I won't execute!")
end
if not nil then
    print("Not nil is true: "..tostring(not nil))
end
if 2 then
    print("Number!")
end
if {} then
    print("Table!")
end

If statements also have else and elseif clauses.
If one thing happens do this, otherwise, if this (elseif) then do this, otherwise (else) do this

if thing1 then
  -- thing1
elseif thing2 then
  -- not thing1, but thing2
else
  -- not thing1 or thing2
end

There are many statements that do different things, like the do statement from earlier, but if statements are one of the most important statements in programming because they make up all of the logic of your code.

Loops

Loops are super important too. They let you run code for all of the items in an array or dictionary or repeat things a certain number of times. They can also repeat forever, or until a condition is met, allowing you to do something repetitively without writing a function call for every one of them.
Prepare for a lot of information!

There are three main types of loops.
While and repeat loops

while myCondition do -- These loops repeat while a condition is truthy. That works like an if statement does.
	-- Stuff
end
repeat -- These loops are like while loops but they repeat *until* a condition becomes truthy. They are like the opposite of while loops, but, they also run their code before they check their condition, allowing you to always run their code at least once.
	-- Stuff
until myCondition

-- Repeat loops can also be represented as a while loop:
-- Stuff (since the condition is checked after code runs in a repeat until loop)
while not myCondition do -- This will keep looping *until* myCondition becomes true.
	-- Stuff
end

For loops

-- There are two main types of for loops
-- There are these loops, which "count". You can use them to repeat something any number of times.
for i=1, 10 do -- i is a local. It represents the current "index." It can be named anything you want!
	print(i) -- The index gets printed. You would see the numbers from 1 to 10 in your output
end
for i=1, 10, 2 do -- For loops like these also have a third option. This is the "step" option. It represents how much to add to i every time the loop repeats (iterates). It can even be negative.
	print(i) -- You should see the odd numbers from 1 to 10.
	i = i + 100 -- You can also add to i and it won't effect the next iteration of the loop.
	warn("I added 100 to i! "..i)
end
-- The second main type of for loop are these loops. These are also known as "foreach" loops because they loop "for each" thing in an array or dictionary
local tbl = {
	["abc"] = 123,
	[1] = "abc",
	"def" -- This actually has index 2. It's like writing [2] = "def"
	[3] = "I am number 3!", -- That means that you don't need to write [3] here
	"I am number 4!",
	"I am number 5!",
	nil -- This is nil. Watch out for this later!
	"I am number 6!",
	[{My="table"}] = "I have a non-string index!",
	[{My="table"}] = "I have a non-string index too! (Notice how I didn't overwrite the previous index) \
		All complex data types (non-strings, non-numbers, non-booleans, non-nil, etc. \
		Tables, Instances, Vector3s, and all others are complex) are always unique even if their content is the same." -- This string also spans multiple lines. Using \ before each new line will make sure it stays there, similar to a long string using [[ and ]]. You can also write \n and it will be a new line in your string, just like if you press enter.
}
for index, value in pairs(tbl) do -- This loop will loop through table giving you each index and the corresponding value. This condition is always true: tbl[index] == value.
	print(index, "=", value) -- Using commas in print, warn, or error will add a space between each item. I prefer to use commas sometimes because it types faster and is sometimes easier to read.
	-- You should see every index and its value!
end

-- But there are also these loops:
for _, value in ipairs(tbl) do -- If you change the _ to any variable name the value of that variable will be the numeric index. _ has some functionality in loops and function parameters.
	-- It represents "no variable." Setting _ to something will truly create a variable with the "_" name but when used in loops and function parameters it doesn't create a variable.
	-- That means that there's no variable to clean up later which can ever so slightly improve performance and reduce memory usage but it's not something to worry about. This is simply considered a "good practice" even though it doesn't offer much benefit.
	print(value) -- This only prints "array-like" values. "array-like" values have an integer index from 1 to infinity. If you have an integer index set to nil *anywhere* in your table it will stop iterating.
	-- You should see all of the values up to index 5 because there's a gap at index 6 which is nil!
end

-- And finally, function based for loops and next loops:
for index, value in next, tbl do -- The "tbl" value is passed to "next" (which is a function) as its first argument. Then the arguments that next returned previously are passed after it.

end
-- ipairs and pairs loops actually both return a function, just like above, and this is how those loops work

local function iteratorFunction(my123Value, lastKey, lastValue, ...) -- This is exactly like the function pairs returns. Pairs isn't represented in lua though so it's faster. It's called by the for loop when it runs, and it gives us all of the values returned previously and any extra values
	print(my123Value) -- Will always print 123 since we pass it in our loop
	return next(tbl, lastKey) -- This returns the next index and value after lastKey
end

for index, value in iteratorFunction, 123 do -- This uses the iterator function we created to get an index and a value. It passes 123 as the first argument and then index, value.
	print(index, "=", value)
end

Concepts

These are the basics of Roblox. These are what you should know about to use the documentation on https://developer.roblox.com

Properties

These are like variables but they exist on an Instance. For example, parts have the Anchored property which can be true or false.
You can think of an Instance a lot like a table.

Methods

These are actually just like properties, but they are functions instead. They offer you extra functionality that properties can’t.
For example:

local Destroy = part.Destroy -- This is a function!
Destroy() -- But why can't we call it?
-- It uses a colon (:)
-- But what does : do?
Destroy(part) -- : just gives the function an extra argument, so when you call part:Destroy() you actually call part.Destroy(part)
local tbl = {}
function tbl:func()
	print(self) -- Same as below
end 
function tbl.func2(self)
	print(self) -- Same as above
end
print(tbl) -- This will print out an id for a table
tbl:func() -- This will pass tbl as the first argument
tbl:func2() -- And so will this
tbl.func(tbl) -- And here's what it looks like without :

-- All of them print the same table id

Events

Events are similar to instances.
They have two functions, Connect and Wait.
Connect will call a function when the event is fired.
For example Instances have a ChildAdded event which is fired whenever an instance is added to it aka “parented” to it.
:Wait will wait until the next time the event is fired.

local myEvent = Instance.new("BindableEvent")
myEvent.Event:Connect(print) -- Will call print when we fire it! Event is an Event on the Instance BindableEvent. It's very similar to a property.

myEvent:Fire("abc")

Getting instances

Instances have FindFirstChild, WaitForChild, and GetChildren functions. GetChildren returns an array of instances which are the “children” of the target instance. FindFirstChild looks for an Instance with a given name and returns it. If it doesn’t exist it returns nil! WaitForChild is similar, but it waits for the instance to exist instead.

You should read the documentation pages for them!
The Instance class.
WaitForChild
FindFirstChild
GetChildren

The dos and donts

How should you find information?

Google! Googling your problems is a great place to find information. You can find everything you need on Google including devforum posts and documentation. If you’re looking for something specific though you should search for documentation directly or look on the devforum!

Neatness is important

When writing Roblox scripts I would recommend keeping your code neat. If your code is readable it means you can look back at it in the future! It’s important for you and others to be able to read your code so they can understand what it does and maybe give some tips on what you could do differently! It also gives you opportunity to reflect on your work and see how far you’ve gone.

That means name your variables clearly and indent your code!

Capitalization can give you context!

This isn’t super important but you should keep it in mind! Make sure your capitalization style is consistent. Often times (but not always) you want variables to start with a lower case letter unless it is a class, Instance, Service, or important variable. That lets people know ahead of time what a variable might be used for. It’s by no means the end of the world if your capitalization doesn’t follow that rule as long as it’s understandable and consistent!

Services in Roblox

Usually when using Roblox services people will recommend that you keep services in variables and keep them with the same name. This is generally a good idea because it lets people reading your code know what services you use before hand and it makes editing and reading code code much easier!

Example:

local ServerScriptService = game:GetService("ServerScriptService")

This format allows you to quickly double click on service names and see where they are used. It also lets you easily replace them if you make a mistake. It also helps you keep your code more organized and readable.

It’s okay to copy code - Sometimes!

Copying code from people is great! Trying to understand other people’s code is how most developers learn. It allows you to pick up on new tricks and better formats. Not everyone is perfect so it’s great to learn from people who have learned something you haven’t learned yet. But always make sure you are not using code without permission! Free models are a great place to find code, but be careful when using them in your game because a lot of them contain malicious scripts. And most importantly of all, make sure you never claim someone else’s code as your own!

219 Likes

This scripting basics tutorial is great; it seems pretty easy to follow, and it’s way better than some tutorials I’ve seen. From what I can tell, all the ideas there are right, but some of your terminology is off. I’m not trying to say this post is bad, but using the official terms would make it even better.

When I think “a way to run code,” I think of functions. do is just a way to enter a new scope and isn’t used for much on its own.

Also, variables can contain more than you listed: they can have numbers, tables, strings, booleans, userdata, functions, threads(?) or nil. local function x() is just syntactic sugar for local x = function(). I feel like it’s worth mentioning all the types a variable can be, although threads/coroutines are probably not the best beginner topic.

Variables are a name you assign a value to, like x = 3. When you call a function with a specific value, that value is an argument being passed as a parameter to that function. This is easy to get confused on, which is why there’s (luckily) a tutorial on it. On a related note, although this is mostly nitpicking at this point, when you use ... as a parameter it has a specific name. It’s called varargs or variadic arguments. It represents that the function can be called with a variable number of arguments.

... itself is a tuple, which is how you refer to multiple arguments at once.

26 Likes

I do agree to an extent that I may not be using terminology accurately. I just want to explain it in a way that’s easy for anyone to understand rather than throwing too many terms at people. I’ll adjust some of the phrasing in my post though just to make sure thing are a bit clearer.

5 Likes

Yeah, that makes sense. Since you link to the developer hub, I’m sure people can figure out the terms anyway. I was mostly worried that the wording might make it seem confusing to beginners - like if variables were both parameters and what they actually are.

3 Likes

Yeah I can understand that. I adjusted the wording a bit. I think it’s more clear now and addresses the terms a little better.

I also added some new sections. (Mainly about finding instances)

3 Likes

No. It’s actually syntactic sugar for local x; x = function().

They’re still variables. You can assign values to parameters, and internally Lua treats them exactly the same as a local variable.

6 Likes

I like this short tutorial however:

Indeeed they’re numbers yet they have 2 types which are integers (whole numbers) and floats/doubles (numbers which have a decimal point). The script will read these as 2 different types so you do need to give the correct one.

6 Likes

If i was a beginner at programming, I would want to be taught the correct terminology rather than taught the wrong terminology… who really cares about the difficulty…

14 Likes

If it’s simplified, it creates an easier entry point. Once you understand the concepts in a way easier for you, then you can learn the proper terminology to use when discussing or presenting your work. This guide is meant for people who have no knowledge, not those who have the knowledge.

6 Likes

But you gain knowledge by learning the correct information not the incorrect information… learning the proper terminology is basically the same difficulty level as learning the incorrect terminology except you are actually learning something in one situation.

3 Likes

Lua (at least this version and predecessors) only has a single number type. double is used for all native numbers.

7 Likes

I call them parameters.

DISCLAIMER: I’m in no position to speak seeing as I haven’t even attempted to make a scripting tutorial (for Lua) before, so just take what I say with a pinch of salt.

Whilst simplification is good and all, over-simplification isn’t the best either.

Personally, if I saw that when I was a beginner programmer (which was way before I even learnt decimals and fractions where a thing), I would assume that it would be limited to integers and would be at a stump whenever I needed decimals.

You missed off a really important part to data types, being booleans. >:(

For variables, mentioning the difference between constants & variables, as well as the _G. variable type (never used this before, makes variable usable across multiple script) could be helpful, as well as that the variable types used in your snippets are all limited to the script that they were initialised in. Local variables also initialise faster, I believe (correct me if I’m wrong, can easily be tested).

The positioning is a bit hectic, I frowned after seeing functions coming up twice - though you could say the same for this post.

If I were to go about an order (this is all me, ya’ll can ignore) for something like this:

  • I’d first address the different data types (strings, integers, booleans etc) and how Lua is different so certain other languages were both integers and floats/doubles/decimal are all treated as numbers.
  • Variables & Constants. Differences, how Lua doesn’t require the type of variable (nor the data type) of a variable to be called along with it. Different types of variables and uses.
  • Functions & Procedures - different use cases etc.
  • The three types of “statements” (maybe more, my programming teacher probably lied to us) - being sequence (i.e. “normal” code), iteration (i.e. loops etc) and selection (i.e. if statements - I call them conditionals). Uses, different types of the different types (i.e. for iteration, while loops, repeat … until loops, etc)
  • Debugging - Good idea to add that

Other stuff :smiley:

Though, good job with the guide…

Nice last paragraph
10 Likes

The first thing I learnt when I was learning to script wasn’t functions, nor variables, nor anything else.

It was learning the correct terminology, specifically the word:

Boolean

(Which took me 3 years to memorise)

And yes, I still have crap memory.

3 Likes

This is just a table set on a global variable, not a variable type. It doesn’t really have a place in a beginner tutorial.

6 Likes

Thank you for all of the feedback! I’ll add some more information on the numbers bit, and add information about booleans (seriously don’t know how I missed those haha). I was planning on getting to statements, I didn’t quite have time last night to formalize those.

However, in terms of other programming languages this is more meant to be a guide to Roblox lua specifically rather than a full on guide to programming. My biggest reason for making this is simply I see a lot of confusion among new scripters. I want to address and explain some of the topics that aren’t always addressed so frequently in tutorials due to their main focus being programming rather than specifically Roblox.

4 Likes

Yes… totally know what that means. Never used it before so no clue how it works, just assumed it was a variable type.

My version of logic dictates (from what you said) that a _G. “variable” is just a global variable that’s added to a table shared between scripts? Correct or incorrect inference?

2 Likes

Wow, what Lua tutorials have you seen? Would love some links or site names because whenever I ever tried to check Lua tutorials, they’d always use Roblox Studio for it (unless it’s the Lua documentation site thing).

2 Likes

Thank you for this great tutorial. This will massively benefit me. Not because I am learning to code, but because I can send a link to this in response to anyone asking me how to learn to code or how I learnt the basics.

3 Likes

You can learn anyway that works for you, everyone is different. I’m simply stating that making it easy to understand is the point of this post. I learned how to use many things in scripting without even knowing what those things were called.

2 Likes

Again this is an entry point topic. The information is correct, just not using the terminology. If I teach someone that the number 10 times the number 10 equals 100, they would know what kids learn both as times tables and multiplication tables. We’re both not wrong, I’m simply stating that you can learn how things work and alternative names and methods that are simpler to understand prior to learning a lot of fancy names and what not. It makes it easier since the target audience of the platform are children.

3 Likes