This post explained all about _G
Is it bad practice to make a global value that represents the localplayer?
Yes. You can already access the LocalPlayer conveniently as a property of the Players service across any LocalScript. If you have a framework, you can store a reference to the LocalPlayer in your framework table when it’s passed around/attached to other code. There’s virtually no need to use _G for this.
i meant when serverscripts want to access the player
Still no because LocalPlayer isn’t set on the server and shared/_G don’t replicate across environments. If the server needs to interact with a player there’s a good chance your system will be able to give the player over or you can index them in the Players service directly by name or otherwise.
is there a circumstance where _G should be used, even if it’s very situational?
Never. There is never a case where you need to, should or should want to use _G. Only very old games may encounter situational cases where it’s useful to expose something to _G and they don’t have the capacity to fully rework systems (yet). New work will never have this problem and as such should never be using _G. ModuleScripts cover every use case _G originally had and can be better tailored for your game’s structure.
reminder that you should use modulescripts instead of using _G.
it’s fine to use it for executing code from the developer console
e.x. _G.dothisfunctioninsideofascript(…)
I’m not sure if this is considered bad on my end. In my frameworks, I store Utility modules inside of _G.Utilities
, some of these modules include:
- Welding
- Animation
- Tweening
Is this considered bad practice? I find it extremely useful; as I don’t have to require the function in every script.
Edit:
After reading this, I realized I could easily store all of the Utility modules inside of well, a ModuleScript that returns a table.
You’ll have to do some sort of polling like repeat wait() until _G.Utilities
because you can’t guarantee it will be set in other scripts. Race conditions can be nasty. You also don’t get good autocomplete. You shouldn’t use something solely out of “convenience” (notice the quotes!) – it can backfire.
In most of the scripts I’m using, _G.Utilities
has already loaded, but that is something to take into account. I’ll move toward ModuleScripts holding utility modules.
If you go in a server script and put
_G.PlayerName = "LightBeam_Studio"
Then in a local script do
print(_G.PlayerNane)
Would this work?
No, there is a separate table on every machine. Modules and attributes might prove to be better for this
Is _G
's metatable locked? If not you could use __newindex
to handle that possibly;
Now you are unnecessarily complicating your code just for this. _G
doesn’t even have a metatable as far as I am aware, but it would be several times easier to just use modules at that point
I’ve got a question:
If you use _G in a localscript, will it still save to server scripts?
no, it’s specific to the session and device
I see, thanks for clarifying that.
Some developers say the use of _G is bad practise but in my opinion it is not. From my point of view, I recommend only using _G when it is absolutely necessary, and to use it to define the main game services, e.g. ReplicatedStorage, ServerScriptService, SeverStorage, etc. I use the main game services in almost all the scripts I write and making them global is a good idea, but other developers use ModuleScripts and a combination of both. I also don’t see Roblox deprecating _G anytime soon, either.
I reckon even in this case, its better to use a ModuleScript rather than _G. You still have to define each _G.[Service] at some point, and you still have to check that it exists before attempting to access it. If you use a ModuleScript instead, you keep all of that code in one place and only have to check that one module exists (as opposed to making a separate check for each service). This leaves you with less redundant and hard to parse code sitting in your scripts.
Part of the problem with using _G is that it’s accessible in every script, not just scripts that explicitly require it. It’s much easier to make changes to how your scripts behave if related code is grouped together, rather than spread across several scripts.