This is a guide about Lua code style. It’s important to keep all code consistent across scripts, especially when working in teams. Thus, I’ve compiled a list of style conventions that should be used to help keep all code clean and orderly. This may be edited and updated as time passes.
I’ve based this off of two other Lua style guides.
1.) Roblox’s style guide
2.) A lua style guide from Ovine Labs
Also, I’ve left out certain sections as I did not consider them very necessary. Sections may be added as time passes.
File Structure
Files should consist of these things (if present) in order:
1.) Services used by the file, using Get Service
2.) Module imports
3.) Constants
4.) Variables and Functions
Variables and Naming Conventions
-
Always try to assign variables at the top of their scope whenever possible. This makes it easier to check for existing variables.
-
Always try to use
local
to declare variables.
Good:
local newBoolVariable = true
Bad:
newBoolVariable = false
-
A File’s name should match the name of the object it exports.
- If your module exports a single function named
doSomething
, the file should be nameddoSomething.lua
.
- If your module exports a single function named
-
When assigning variables and other names, make sure to spell out words fully. Abbreviations take up less space, but are not as easy to read.
-
Use
camelCase
for assigning names to local variables.(Member variable - Wikipedia) -
Use
Upper_Snake_Case
for local constant values that do not change. -
Use
PascalCase
for everything else
local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local Running_Velocity = 50 local Walking_Velocity = 25 local isWalking = false local isRunning = false local PlayerCharacter = {} local function PlayerCharacter.IsMoving() return isRunning or isWalking end
Tables
-
Avoid tables with both list-like and dictionary-like keys. Iterating over these mixed tables is troublesome.
-
Iterate over list-like tables with
ipairs
and dictionary-like tables withpairs
. This helps clarify what kind of table we’re expecting in a given block of code. -
Break dictionary-like tables with more than a couple keys onto multiple lines. This makes it easier to read and understand what is inside the table.
Good:
local Inventory = { backpack = {}, belt = {}, primaryWeapon = "Hatchet", }
Bad:
local Inventory = {backpack = {}, belt = {}, primaryWeapon = "Hatchet"}
- Use the constructor syntax for table creation whenever possible. This just makes it easier to understand what is membered inside the table.
Good:
local Beans = { quality = 90 hungerRefill = 80 thirstRefill = 10 }
Bad:
local Beans = {} Beans.quality = 90 Beans.hungerRefill = 80 Beans.thirstRefill = 10
- Define functions externally to table definition
Good:
local Beans = { quality = 90 hungerRefill = 80 thirstRefill = 10 } function Beans:eat() -- EAT DEM BEANS!!! end
Bad:
local Beans = { quality = 90 hungerRefill = 80 thirstRefill = 10 eat = function() -- eat dem beans ;( end }
Functions
-
Declare functions using
local
whenever possible.- Sometimes, exceptions are made. An exception can be made for late-initializing functions in conditionals. However, notice how the function is still tied to a local value.
local doSomething if _Condition then function doSomething() -- Version of doSomething with _Condition enabled end else function doSomething() -- Version of doSomething with _Condition disabled end end
-
Try to keep functions as small, and as focused on one goal as humanly possible. This is one of the most important things for well organized, clean, and readable code. Most important!
-
Keep arguments in a function limited to as few as possible.
-
When declaring a function that is membered to a table, use function-prefix syntax. Differentiate between
.
and:
to denote intended calling convention.-
If the function calls an event or action, use
:
-
If the function returns a value, use
.
-
Pet = {} function Pet:walkTo(position) -- walks the pet to position end function Pet.getName() -- returns the pet's name end
- When declaring any function, prefer function syntax over variable syntax.
Good:
local function newFunction() -- Stuff here end
Bad:
local newFunction = function() -- Stuff here end
- Perform validation to functions as early as possible. This is to make sure no extra resources are being used that aren’t necessary.
local canRunNewFunction = false local function newFunction() if not canRunNewFunction then return end print ("Running newFunction") -- Since canRunNewFunction is false, -- the rest of the function will not run. end
Code Blocks
- Single line blocks are okay for small statements. Try to keep lines to 80 characters. Indent lines if they overflow past the limit.
if true then return true end -- This is okay because it's small and simple to read
- Use
do
blocks if limiting the scope of a variable is necessary.
local getId do local lastId = 0 function getId() lastId = lastId + 1 return lastId end end
Strings
-
For most cases, strings should be defined by double quotes
- There are some exceptions. For example, sometimes a string needs to actually have quotation marks in the string itself. In this scenario, brackets can be used.
print ([["By God! That's an exception!", he exclaimed.]])
- Strings longer than 80 characters should be written across multiple lines using concatenation. This allows you to indent nicely.
Good:
superLongString = "This is a super long string that ".. "I am writing for the purpose of ".. "this resource. As you can see, ".. "it is not on one line and is much".. "easier to read! This is the best ".. "way to do if if you want to read ".. "it easily."
Bad:
superLongString = "This is a super long string that I am writing for the purpose of this resource. As you can see, it is on one line and it is hard to read! This is not the best way to do it if you want to read it easily.
Whitespace
Whitespace is one of the most important things to keep in check for clean and readable code.
-
Always use proper indentation with tabs.
- Seriously, though, indent with tabs
-
Avoid leaving whitespace at the end of lines.
-
Use one statement per line. Prefer to put function bodies on new lines.
-
No vertical alignment. It just looks ugly.
Good:
variableLong1 = true variable2 = false
Bad:
variableLong1 = true variable2 = false
-
Use a single empty line to express groups when useful. Do not start blocks with a blank line. Excess empty lines harm whole-file readability.
-
Put a space before and after operators
-
Put a space after commas
Good:
function add(a, b) return a + b end
Bad:
function add(a,b) return a+b end
- When creating blocks, inline any opening syntax elements.
Good:
local foo = { bar = 2, } if foo then -- do something end
Bad:
local foo = { bar = 2, } if foo then -- do something end