As a new — or relatively new — Lua/Solar2D programmer, are you confused by console errors like this?
Runtime error /Users/yourname/Projects/AwesomeGame\menu.lua:4: attempt to index global 'button' (a nil value)
stack traceback:
[C]: in function 'error'
?: in function 'gotoScene'
/Users/yourname/Projects/AwesomeGame\main.lua:16: in main chunk
If so, then you need to learn a very important programming concept known as scope. Scope impacts Lua’s ability to “see” variables
When you think of terms like “telescope” or “microscope,” you think of devices that help you see, and see things within a limit — for instance, very small things in a microscope. In programming terms, scope is used to define what parts of your code can “see” variables, objects, and functions that you have created. In Lua, there are two main scope controls: global and local.

Global variables/functions can be seen anywhere in your program. “Great, I’ll use global scope for everything!” you might say, but global objects can actually be quite bad! In fact, new programmers should avoid using global variables.
One reason why globals are dangerous is that — because they have no visibility limits — they can be expensive to use in regards to performance. In fact, if a global variable is accessed in a
Global variables/functions also have the inherent risk of being accidentally _W in one Lua file and assign it a value of 320, you may accidentally create another global variable _W in another file, assign it a different value, and effectively “trash” the first declaration. This could obviously have unexpected consequences in the first file which expects _W to have a value of 320!
The global scope is discussed in more detail in the Goodbye Globals! tutorial, along with a convenient method to create/access
In Lua, the preferred scope is local which you control by using the local declaration before you define a variable/function. For example:
local someVariable
local function someFunction() end
When you prefix a variable or function with local when you first create it, it becomes available to that block of code and any “children” blocks contained within. This concept is highlighted by the following two examples:
local function addTwoNumbers( number1, number2 )
-- Create variable "sum" local only to this "addTwoNumbers()" function
local sum = number1 + number2
print( sum ) -- This works!
end
print( sum ) -- This does NOT work (prints "nil" meaning it's unknown to Lua)
In this case, the function addTwoNumbers() defines a new block of code. Inside this block, we create a new variable named sum. This variable has the local keyword, meaning it’s only visible to the function addTwoNumbers() — no other code in this module or overall project will be able to “see” the sum variable. Thus, when the function ends, there is no longer a variable known as sum and nil will be printed to the console.
local function addTwoNumbers( number1, number2 )
local sum = number1 + number2
if sum < 10 then
print( sum .. " is less than 10" )
local secondSum = sum + 10
end
print( secondSum ) -- This does NOT work (prints "nil" meaning it's unknown to Lua)
end
Like the first example, sum is local to addTwoNumbers(). That lets us add two numbers, and it’s also visible inside the block started by if sum < 10 thenif-thensecondSum) is created, and that variable becomes local only to the if-thensecondSum outside of the if-thennil because secondSum doesn’t exist at that point in execution.
Consider a block of code like this:
local i = 999
for i = 1, 10 do
print( i ) -- prints 1, 2, 3, .. 10
end
print( i ) -- prints 999
Here, a local variable i is set to 999 on line 1. In addition, a loop index variable of i (line 3) is used, but this i is local only to the for loop. As the loop executes, its value represents the values 1-10print( i )i will forget its final value from the loop and return to its previous definition (usually nil). Following that, the local variable i which was declared before the for loop is printed to the console (print( i ) on line 7999. This is because for loops — just like functions — are blocks and they adhere to the same scope rules associated with blocks.
Hopefully, this tutorial has illustrated that scope, as an overall concept, is relatively straightforward. When you use the keyword local, the variable can only be accessed at that block level or within any child blocks. With that in mind, if your variables or functions need to be seen at a wider level, simply move them above/outside the block or define them near the top of the module.