_G Variable even though set is displayed as nil on other scripts

LOCALSCRIPT that recieves the code from server [in replicatedfirst]

local ReplicatedStorage = game:GetService('ReplicatedStorage')
ReplicatedStorage:WaitForChild('Remotes', math.huge):WaitForChild('Server Call', math.huge).OnClientInvoke = function(NewCode)
	if (NewCode == nil or tonumber(NewCode) == nil) then
		return false
	end

	_G.ServerId = NewCode

	warn("ServerId set to: " .. _G.ServerId)
	return true
end

another local script to print the global variable to see if it works

task.delay(3, function()
	warn(_G.ServerId)
end)

whats displayed by another localscript after a 3 second delay:

1 Like

Okay first off, what is the point of adding a timeout to your :WaitForChild if you’re gonna set it to basically infinite.

Second off, I need to see the Server Script in order to truly deduce what’s going on here, because it seems like the error being displayed is from the server receiving an invalid player object.

because a waitforchild doesnt wait for ‘infinite’ until you set a infinite timeout? for example what if my game was really costly and took too long to load and didnt load in the default 3-5 second duration timeout

Don’t use _G, it is bad practice. When your game gets bigger, you will need to see the declarations for everything you use (because you can’t remember everything). Using _G will make your life harder as a developer.

You should use a ModuleScript for this. If you didnt know, every time you require a module past the first time, the same table is returned. So you can just use a ModuleScript as a way to store variables that multiple scripts need to access and modify

Note: ModuleScripts are only the same in the same RunContext. For example, if the server requires a module in ReplicatedStorage, and then the client does too, they are different tables despite what I just said

1 Like

I believe _G is old and bad to use.
You should potentially use a string value or a number value, or if you only need to access the server Id from that bindable function, you can just return the server Id.
Another potential solution is using a module script and accessing a variable through it
example :

local module = {}
module.ServerId = yourserverid
return module

and after access the server Id from your other scripts

2 Likes

You shouldn’t even be using waitforchild period. If you correctly load your game you shouldn’t have to worry about using waitforchild, especially infinitely yielding your own script over it is outrageous. Time out 3-5 seconds if it doesnt. retry, if it fails again instance doesn’t exist most likely or you have a laggy client. I don’t even think the biggest complex games don’t use an infinite wait.

its wrapped around a task.spawn, and its for safe measures. ive seen many games use math.huge as timeout, atleast some games that take too long to load

whilst your solution is a solution, think about why i made a table in server for ‘loaded player access’ and called it a ‘serverid’ in client, its so players have to fire events using that id otherwise they’d be counted as exploiting.

creating a module for one single thing would feel unoptimable, and that the id will be turned into nil after a certain duration of time so its unaccessible anymore to prevent any exploits

Huhhh. This makes no sense this security you are implementing. A haxor could easily bypass this _G, also that is going to lag your game even more sending through unnecessary params through a remote.

I believe that @protaki1’s solution is the more standard and performant solution.

lag? how is a id thats about 0.02kb and lasts temporarily going to cause lag…
now his solution is his own suggestion?

if your answer is not a solution to my question and just a suggestion/belief then stop posting on the forum?

This is not true. :WaitForChild by default will wait forever, just that it will print a warning if it waits for more than 5 seconds. You set an infinite time limit simply to make it shut up, or a finite time limit if you don’t want it to yield forever.

In that case, you’re better off storing the value as an attribute of a common instance, such as workspace. It still carries the benefit of autocomplete that came with using modulescripts.

workspace:SetAttribute("ServerId", 123456)

task.delay(3, warn, workspace:GetAttribute("ServerId"))

My apologies if i came off rude,
Could you try and use a remote event and fire the client, if you are using a bindable event (OnClientInvoke)? or a remote function?

– and then fire the client the server id. then use the _G.ServerId = NewCode and see if you are able to access it there.

1 Like

No worries, i just prefer getting a solution to my answer, its not as if i dont already know _G is believed to be ‘unreliable’ & ‘old’ by others, i just prefer to use it.

Yes this works and just seems to be the only solution i can see in this entire forum, thank you

1 Like

My bad for being misinformed about waitforchild, the warning label just feels like it paused the entire code and errored

Yeah this is also a viable solution just prefer if it was about _G, aka my original issue

Yep no worries as well, Good Luck on your project! :slight_smile:

May I kindly refer you to the XY Problem in the future. It’s way easier to give and receive assistance if you ask about your goal instead of an attempted solution for a goal. Many people have reservations about using _G, which, proven by the replies in this thread, derails the topic and causes a lot of confusion.

is it not visible that i was aiming to find out why a global variable was seen as nil by other scripts, but in the main script its not nil? none actually tried to provide help about the original issue and rather gave me their personal opinions and gave me critiques of my way of coding

Perhaps if you reworded your question to include the reason why you wanted to use global variables, people would be less inclined to talk about _G specifically. If it was about storing the ServerId to be universally accessible, there are many alternatives, but people assumed you wanted to only use _G.