Table of Contents
Why Data Types Matter
In Lua, every value has a type. A type describes what kind of thing the value is, such as a number, a piece of text, or a true or false value. Roblox scripts constantly work with different types, and using the wrong type in the wrong place usually causes errors.
Whenever you store something in a variable, pass it into a function, or get something from Roblox, you are dealing with data types. Understanding them lets you read error messages more easily and avoid confusing bugs.
Important rule: every value in Lua has exactly one type at a time. A value cannot be both a number and a string, or both a boolean and a table.
Lua has a small set of basic types that you will use everywhere. Roblox adds extra, Roblox-specific types, which you will meet later when you script with parts, vectors, and colors.
The `nil` Type
nil means “no value” or “nothing here.” It is a special type in Lua that usually represents the absence of something.
If you read a variable that was never given a value, Lua gives you nil. If you look something up in a table and it is not there, you also get nil.
You can assign it directly:
local nothingHere = nil
print(nothingHere) -- prints nil
Variables that hold nil are treated as if they do not contain a useful value. Many programming mistakes come from accidentally using nil where you expected something else.
Key idea: nil is a real value with its own type. It does not mean zero, it does not mean an empty string, and it does not mean false. It only means “no value.”
The `boolean` Type
A boolean can only be one of two values, true or false. These are used for decisions in your code, especially with if statements.
You create booleans directly or get them from comparisons:
local isJumping = false
local score = 10
local highScore = 20
local brokeRecord = score > highScore -- this is false
local hasHighScore = score >= highScore -- this is also false
In Lua, only false and nil count as false in conditions. Everything else, including 0 and empty strings, counts as true.
Rule: in if conditions, only false and nil are treated as false. All other values, such as 0 or "", are treated as true.
The `number` Type
number represents numeric values. Lua uses one numeric type for both whole numbers and decimal numbers.
You can write them as integers or with decimal points:
local health = 100 -- integer
local speed = 16.5 -- decimal
local gravity = 196.2You use numbers with arithmetic operators. The main ones you will see are:
local a = 10
local b = 3
local sum = a + b -- 13
local diff = a - b -- 7
local product = a * b -- 30
local quotient = a / b -- 3.3333...
local power = a ^ b -- 10^3 = 1000
local remainder = a % b -- 1
Lua also has arithmetic functions in the math library, such as math.floor, math.ceil, and math.random. These will appear later when you add randomness and more precise calculations to your games.
The `string` Type
A string is a piece of text. In Lua, you write strings surrounded by quotes, usually double quotes " or single quotes '.
Examples:
local playerName = "Alex"
local welcome = "Welcome to the game!"
local smallMessage = 'Go!'
You can combine strings using the concatenation operator ..:
local firstName = "Alex"
local greeting = "Hello, " .. firstName
print(greeting) -- Hello, Alex
Strings and numbers are different types, so you cannot add them with +. If you want to combine a string with a number, you must either use .. or convert the number to text.
This works:
local coins = 10
print("You have " .. coins .. " coins.")
Using + in that example would cause an error because + expects numbers on both sides, not a string and a number.
You can find the length of a string using the length operator #:
local word = "Roblox"
local length = #word -- 6The `table` Type
Tables are Lua’s main way to store collections and structured data. A table can hold many values, and each value is stored under a key.
For now, you can think of tables in two common shapes. The first shape is like a list:
local colors = {"Red", "Blue", "Green"}
Here the table holds three strings, and they are automatically indexed starting at 1. So colors[1] is "Red", colors[2] is "Blue", and so on.
The second shape is like a dictionary or record, where you name each key:
local playerInfo = {
Name = "Alex",
Level = 5,
IsVIP = false
}You can read values with:
print(playerInfo.Name) -- AlexTables are very flexible. They can even hold other tables, or functions, or mixed types. Because of that, they are used to represent many game related things, such as inventories, settings, and configuration data.
The `function` Type
Functions are pieces of code that you can run later. They also have their own type, so you can store functions in variables or tables and pass them around.
A function can be defined like this:
local function sayHello()
print("Hello!")
endAlthough the main focus here is that functions are a distinct type in Lua, you will learn how to define and use them more fully in the functions chapter.
The `userdata` and `thread` Types
Lua also has two types called userdata and thread.
In plain Lua, userdata lets external systems attach their own data to Lua. In Roblox, many Roblox objects behave in a similar way through Roblox’s own types, so you will not create raw userdata yourself. Instead, you will work with Roblox specific objects that behave like special values and are integrated into the engine.
thread represents a coroutine, which is a way to pause and resume functions. This is an advanced topic and is not necessary for basic Roblox games. It becomes useful later when you need more control over timing and concurrent behavior.
Roblox Specific Types
On top of Lua’s basic types, Roblox adds many custom types that are used everywhere in Roblox Studio. These include types such as Vector3, CFrame, Color3, and various Instance types like Part or Model.
These values are not plain numbers or tables, even though you can sometimes read numeric fields from them. For example, a Vector3 stores three coordinates, but it is a single value with its own type.
You will meet these Roblox specific types when you begin scripting parts and working with the Workspace. At that point you will use constructors like Vector3.new and Color3.new and pass these values into Roblox functions that expect them.
Checking Types with `type`
Lua provides a built in function called type which tells you the type of any value as a string.
For example:
print(type(10)) -- "number"
print(type("Hello")) -- "string"
print(type(true)) -- "boolean"
print(type(nil)) -- "nil"
print(type({})) -- "table"
local function test() end
print(type(test)) -- "function"
This can help when debugging scripts. If a function expects a number but you accidentally pass a string, a quick print(type(someValue)) can reveal the mistake.
Converting Between Types
Sometimes you need to change a value from one type to another. For example, player input is often a string but you might need a number to do math. Lua gives you basic conversion functions for strings and numbers.
To turn a number into a string, use tostring:
local coins = 5
local text = tostring(coins)
print(type(text)) -- "string"
To turn a string into a number, use tonumber:
local input = "42"
local value = tonumber(input)
print(type(value)) -- "number"
If tonumber cannot convert the string, it returns nil. That is useful to detect invalid input.
Rule: Lua never automatically converts between numbers and strings for you. You must use .. for string concatenation, and you must call tonumber or tostring when you need to change the type.
Using Types Correctly in Roblox Scripts
In Roblox, many functions expect specific types. For example, a property might expect a Color3, another might expect a Vector3, and others expect plain number or string. Passing the wrong type usually causes an error like “invalid argument” or “attempt to index nil.”
When you read the Roblox documentation, check what type each parameter and property expects. Then make sure you pass a value of that type, not something different.
As you practice, type related mistakes will become easier to spot. If you keep the idea clear in your head that every value has one type, and that each operation expects certain types, you will avoid many common errors in your early Roblox scripting.