This is super helpful. Thank you so much!
Couldn’t you organize variables in _G by doing _G.[plr.UserId].Data = {1,1,1}
?
Correct me if I am wrong, but doesn’t that defeat the issue of having organization withing _G?
This is super helpful. Thank you so much!
Couldn’t you organize variables in _G by doing _G.[plr.UserId].Data = {1,1,1}
?
Correct me if I am wrong, but doesn’t that defeat the issue of having organization withing _G?
Immutable state with _G
would still not be good but is only slightly better than mutable global state. I doubt someone’s cash and level is immutable so this is incorrect.
No they aren’t the same at all. Not sure where you got this from.
I don’t think I said that _G and module scripts are exactly the same, they just work very similar, they both hold tables that can be globally accessed and do not replicate over client/server boundary.
About storing player stats, you can use it for player stats just fine, it’s just not recommended if you use huge player stats with inventories and such for example.
It’s fine to use _G, but not recommended for complex or large tables and such.
If modules are “very similar” to _G
you might as well use modules. Write more modular code instead.
It is not fine to use _G
, I can’t think of a use case where you would want to pollute the global environment.
How would you go about using a module similar to the usage of _G?
As in… module.Thing = 1
would not transfer between scripts.
I also stated that it’s recommended to use modules, modular systems are more readable and sorted.
But if people really want to use _G for something, we should not entirely stop them from doing so.
Sure using _G can be a hassle when trying to keep things organized and such, but I’ve also seen a lot of scripters make up random reasons as to why not to use _G that barely made sense…
So again, modules are recommended, but if you want to use _G for small and simple global variables and such, it’s fine to do so, if you stumble upon a problem, scripting support exists for reasons.
It will transfer between scripts if multiple scripts require() the same module.
You would just require
the module when you need it. That is a good thing. By using _G
it is basically everywhere. When using modules your “global variables” are only there when you need them.
we should because it introduces bad habits when code should be modular by nature
So this will work?
Module:
return{"Test"}
Script 1:
module.Table[1] = "Hello"
Script 2:
print(module.Table[1]) -- Prints "Hello"
require
calls are memoized and it always returns the same reference.
If your module returns a table and script 1 and script 2 requires it as well they both have reference to the same table.
Might I also add:
By using _G
you have to do some awful hack like
repeat
wait()
until _G.your_variable ~= nil
to guarantee that the variable exists just in case the scripts that use it load before the scripts that actually declare it do.
Which is one hell of a disadvantage. Modules don’t ever have this issue.
Your module script:
local mod = {}
mod.my_var = 1
Script 1:
local my_mod = require(game.Workspace.ModuleScript)
print(my_mod.my_var) --prints 1
my_mod.my_var = 20
Script 2:
local my_mod = require(game.Workspace.ModuleScript)
print(my_mod.my_var) --prints 20
my_mod.my_var = 5
Script 3:
local my_mod = require(game.Workspace.ModuleScript)
print(my_mod.my_var) --prints 5
Hope that makes it understandable.
I’d also like to add on, client and server don’t share the same memory, since they are on different machines after all.
So not only is lua’s global table not replicated from server - > client, or client → server. But no table is replicated or shared over the boundary unless user defined.
Lets say you have some table and pass it in as an argument to a remote event/ function. Internally this table is encoded/decoded to/from a JSON-formatted string. This then creates a different table (on client if sent from server and vise versa) with a reference which can only be accessed on the machine its stored on.
Like…?
This is a year old thread and it’s not particularly related to the question OP is asking, but there is virtually no reason to be using _G in 2021. ModuleScripts can do what _G would commonly be used for. Developer globals have almost no place in Roblox development.
As for your latter post, bumping is making a comment on an old thread that doesn’t add discussion value to a thread. This is fine but if you’re asking as a question and if it’s related to OP’s topic.
_G is useful if you don’t necessarily NEED huge tables of variables and stuff and you only need to make one variable global to other scripts.
You can still use ModuleScripts for that or pass them around as variables either through pure Lua, attributes or ValueBase objects. _G is unnecessary. Don’t use globals if you don’t need them, which in nearly all cases you don’t and can import them from somewhere better.
Might just be me and my laziness but I use _G to store required modules lol
Ad hominem attacks aren’t what you should be getting out of this or any similar such conversation; it’s that using globals is unnecessary and dare I say bad practice. Local variables are faster, can be accessed right from the stack and there are better ways to do what you’re looking to do.
_G has virtually no place in production code as it stands now. All members of that table are globals unless you declare them locally which in that instance you can just settle for better solutions that involve them being in scope. You can easily pull your variables in using more conventional methods and even better if your code structuring is well done, e.g. a framework!
Feel free to look for a similar discussion topic or start a new one based on _G. This isn’t related to OP’s topic anymore which is seeking to prevent exploiters from accessing variables in the global table; it’s starting to veer off topic to hone in on one specific point that popped up during discussion when the thread was originally created. Don’t want to hijack the thread.
I just want to add that it is absolutely, undeniably exploitable (with considerable ease). Using module scripts is better is many facets, but you are able to modify and call anything that you return in the module script.
This is true only for the client side, although I agree that modules are superior.