Global Variables

I am using director and I would like to make it so if you press a button on one screen, that changes a variable to be used on another screen.

Example code that does not work because I am dumb:

Screen1.lua
[lua]module(…, package.seeall)
– Main function - MUST return a display.newGroup()
color = 0;
function new()
local localGroup = display.newGroup()

–PreStuFZ
– Background
local background = display.newImage(“bg.png”)
localGroup:insert(background)

–Menu
local bt01 = display.newRect(100,150,100,50)
local function bt01t ( event )
if event.phase == “ended” then
director:changeScene(“screen2”,“moveFromLeft”)
end
end
bt01:addEventListener(“touch”,bt01t)
bt01.x = 160
bt01.y = 200
localGroup:insert(bt01)

local bt02 = display.newRect(100,50,100,50)
local function bt02t ( event )
if event.phase == “ended” then
color = 256;
end
end
bt02:addEventListener(“touch”,bt02t)
bt02.x = 180
bt02.y = 270
localGroup:insert(bt02)

– MUST return a display.newGroup()
return localGroup
end[/lua]

Screen2.lua
[lua]module(…, package.seeall)

– Main function - MUST return a display.newGroup()
function new()
local localGroup = display.newGroup()

local background = display.newImage(“bg.png”)
localGroup:insert(background)

local colorex = display.newRect(100,100,100,100)
colorex:setFillColor(color,color,color)
localGroup:insert(colorex)

– MUST return a display.newGroup()

return localGroup
end[/lua]

Thanks! [import]uid: 30000 topic_id: 5919 reply_id: 305919[/import]

local bt01 = display.newRect(100,150,100,50)
local function bt01t ( event )
if event.phase == “ended” then
_G[“color”] = 0
director:changeScene(“screen2”,“moveFromLeft”)
end
end

I use this _G[“color”] = 0 a lot… but you should make it local on the next screen for speed.
[import]uid: 10657 topic_id: 5919 reply_id: 20325[/import]

I tried that and all I get is this error.

WARNING: display.setStatusBarMode() not supported in the simulator for the current device Runtime error error loading module 'screen1' from file 'E:\Users\Du\Desktop\App\VarsExam\screen1.lua': E:\Users\Du\Desktop\App\VarsExam\screen1.lua:29: '<name>' expected<br> near '['<br>stack traceback:<br> [C]: ?<br> [C]: ?<br> [C]: in function 'require'<br><br> Runtime error: error loading module 'screen1' from file 'E:\Users\Du\Desktop\App\VarsExam\screen1.lua':<br> E:\Users\Du\Desktop\App\VarsExam\screen1.lua:29: '<name>' expected<br> near '['<br>stack traceback:<br> [C]: ?<br> [C]: ?<br> [C]: in function 'require'<br> E:\Users\DuSchiRuntime error<br> E:\Users\Du\Desktop\App\VarsExam\director.lua:135: ERROR: table expected. If this is a function call, you might have used '.' instead of ':'<br>stack traceback:<br> [C]: ?<br> [C]: in function 'insert'<br> E:\Users\Du\Desktop\App\VarsExam\d

All I am trying to achieve is how to create global variables and change them to be used in other screens. To make things and colors to be customizable. [import]uid: 30000 topic_id: 5919 reply_id: 20515[/import]

The answer to your question is very simple. Just declare a variable in main.lua, like this:

xyz = 123  

Unless you say “local”, all variables in Lua are global. No need for anything special, no need for _G or any of that. The errors you’re getting probably have nothing to do with globals.

Here’s a sample test project that works for me.

main.lua

director = require("director")  
xyz = 123  
print("In main, xyz=", xyz)  
director:changeScene("mainmenu")  

mainmenu.lua

module(..., package.seeall)  
function new()  
 local g = display.newGroup()  
 print("In mainmenu, xyz=", xyz)  
 return g  
end  

[import]uid: 9659 topic_id: 5919 reply_id: 20816[/import]

This still seems to have no effect!

Main.lua
[lua]display.setStatusBar( display.HiddenStatusBar )
color = 0

local director = require(“director”)

local mainGroup = display.newGroup()

local function main()
mainGroup:insert(director.directorView)
director:changeScene(“screen1”)
return true
end
main()[/lua]

screen1.lua
[lua]module(…, package.seeall)
– Main function - MUST return a display.newGroup()

function new()
local localGroup = display.newGroup()

–PreStuFZ
– Background
local background = display.newImage(“bg.png”)
localGroup:insert(background)

local poop = display.newText(color,50, 50, native.systemFontBold)
localGroup:insert(poop)

–Menu
local bt01 = display.newRect(100,150,100,50)
local function bt01t ( event )
if event.phase == “ended” then
director:changeScene(“screen2”,“moveFromLeft”)
end
end
bt01:addEventListener(“touch”,bt01t)
bt01.x = 160
bt01.y = 200
localGroup:insert(bt01)

local bt02 = display.newRect(100,50,100,50)
local function bt02t ( event )
if event.phase == “ended” then
color = 256
local poopt = display.newText(color,50, 75, native.systemFontBold)
localGroup:insert(poopt)
end
end
bt02:addEventListener(“touch”,bt02t)
bt02.x = 180
bt02.y = 270
localGroup:insert(bt02)

– MUST return a display.newGroup()
return localGroup
end[/lua]

screen2.lua
[lua]module(…, package.seeall)

– Main function - MUST return a display.newGroup()
function new()
local localGroup = display.newGroup()

local background = display.newImage(“bg.png”)
localGroup:insert(background)

local colorex = display.newRect(100,100,100,100)
colorex:setFillColor(color,0,0)
localGroup:insert(colorex)

– MUST return a display.newGroup()

return localGroup
end[/lua]

:frowning: [import]uid: 30000 topic_id: 5919 reply_id: 21067[/import]

Dude, you forgot to mention what you’re expecting vs. what you’re getting. That’s a lot of code to try to guess at it.
[import]uid: 9659 topic_id: 5919 reply_id: 21070[/import]

Button pressed changes a value on one screen. That same value sticks if it switches to another screen. [import]uid: 30000 topic_id: 5919 reply_id: 21071[/import]

Not specific enough, sorry, I’m tired and going to bed. I’m willing to help, but I’m not going to wade through 75 lines of code to fix your problem for you when you don’t even bother to define what the problem is in specific terms. Have you tried reducing the problem to something very very simple (10-20 lines), like the example I posted?
[import]uid: 9659 topic_id: 5919 reply_id: 21072[/import]

lococo: “Unless you say “local”, all variables in Lua are global.”

that’s not actually quite true

mainmenu.lua
[lua]module(…, package.seeall)
function doSomething()
print(“dosomething in mainmenu”)
xyz=345
_G[“globalXYZ”]=“DEF”
end[/lua]

main.lua
[lua]menu=require(“mainmenu”)

xyz = 123
_G[“globalXYZ”]=“ABC”

print(“xyz=”…xyz) – 123
print(“globalxyz=”…_G[“globalXYZ”]) – ABC

menu.doSomething()

print(“xyz=”…xyz) – still 123
print(“globalxyz=”…_G[“globalXYZ”]) – DEF[/lua]

if you need it to be truly “Global”, it should really use _G
[import]uid: 6645 topic_id: 5919 reply_id: 21114[/import]

Yep, it looks like you’re right. It seems that module(..., package.seeall) is the culprit here, which is interesting. If you define the mainmenu.lua module like this, and leave all other code untouched, it works fine:

local M = {}  
function M.doSomething()  
 print("dosomething in mainmenu")  
 xyz=345  
 \_G["globalXYZ"]="DEF"  
end  
return M  

Very shortly after I started learning Lua I happened to read this wiki page which got me to change all my modules. Ever since then I haven’t had any problems with globals, so I suppose I was lulled into a false sense of security. :slight_smile:

That, combined with the Lua 5.1 Reference saying in section 2.3 “Any variable is assumed to be global unless explicitly declared as a local” made me assume global was global.

One other thing. Anything that’s global in my game tends to be something I’m going to want to save/restore, like user settings, etc. In that case it’s a lot easier if I store them in a table I set aside for that purpose. Globals in tables works fine; it doesn’t have to be the _G table … any table will do:

mainmenu.lua

module(..., package.seeall)  
function doSomething()  
 print("dosomething in mainmenu")  
 xyz=345  
 \_G["globalXYZ"]="DEF"  
 myvars.xyz = 999  
end  

main.lua

menu=require("mainmenu")  
  
myvars = {}  
  
xyz = 123  
\_G["globalXYZ"]="ABC"  
myvars.xyz = "111"   
  
print("xyz="..xyz) -- 123  
print("globalxyz="..\_G["globalXYZ"]) -- ABC  
print("myvars.xyz="..myvars.xyz) -- 111  
  
menu.doSomething()  
  
print("xyz="..xyz) -- still 123  
print("globalxyz="..\_G["globalXYZ"]) -- DEF  
print("myvars.xyz="..myvars.xyz) -- 999  

[import]uid: 9659 topic_id: 5919 reply_id: 21153[/import]

that’s not actually quite true

huh, thanks for that example. That could be what’s causing the tiny memory leak I wasted hours on yesterday before giving up. [import]uid: 12108 topic_id: 5919 reply_id: 21179[/import]

lococo, in your example where you remove “module”, it’s essentially the same as if you put your mainmenu code inside your main.lua. that’s all require is really doing there, that’s why it works

[lua]local M = {}
function M.doSomething()
print(“dosomething in mainmenu”)
xyz=345
_G[“globalXYZ”]=“DEF”
end

local mainmenu=M

xyz = 123
_G[“globalXYZ”]=“ABC”

print(“xyz=”…xyz) – 123
print(“globalxyz=”…_G[“globalXYZ”]) – ABC

mainmenu.doSomething()

print(“xyz=”…xyz) – still 123
print(“globalxyz=”…_G[“globalXYZ”]) – DEF[/lua]
[import]uid: 6645 topic_id: 5919 reply_id: 21187[/import]

One of the effects of the module function is to change the environment of the code that calls module. What that means is that any global assignments in the rest of that file go into the module table, rather than the thread environment. Using package.seeall with module allows global lookups to retrieve values from the thread global environment (which is how reference is to _G work inside a module declaration, actually), but assignments go into the module table.

This usually still means they’re globally accessible. If you make a global assignment in a module “m” to the global “xyz”, outside code can retrieve it as “m.xyz”, because module typically creates the module table in a global variable.

Environments are one of the most confusing aspects of Lua but also among the most powerful. [import]uid: 12678 topic_id: 5919 reply_id: 21569[/import]