is there any way I can get a client to read a _G variable? I only need it to read it! If not, whats like the easiest way to get it replicated? (FE on)
Is there any way I can get a client to read a _G variable?
1 answer
When you write a variable to _G, it only stays on the side you write it.
So if you write it on the Server, it will only be in the server's scripts (running from "Script" Objects)
And if you write it on the client, it will only be in the client's scripts (running from "LocalScript" Objects)
Hence, it's impossible for the client to read a variable stored in _G from the server.
However, you can duplicate the variable onto the client using Remote Events. So first we need to make a Remote Event and put it in the Workspace, where both the server and client can access it
local event = Instance.new("RemoteEvent", workspace)
After that, you need to set up a system where the server will fire the event, and the client will update it's own _G when the event is fired
--On the server (in a Script)
local event = game.Workspace:WaitForChild("RemoteEvent") --Change RemoteEvent to what you named the event to
event:FireClient(player, key, value)
--[[@player: this is the Player object for the corresponding client you want to update
@key: This is a string which refers to the property of _G you are updating
@value: This is what you are updating the property of _G to
]]
--On the client (in a LocalScript)
local event = game.Workspace:WaitForChild("RemoteEvent") --Change RemoteEvent to what you named the event to
event.OnClientEvent:Connect(function(key, value)
_G[key] = value
end)
--This says that when the event is fired, it will take the key and value it was fired with and set the desired value of _G equal to the value. It's like _G.thing = otherthing
Once this system is set up, you would need to fire this event every time you update _G
local event = game.Workspace:WaitForChild("RemoteEvent") --Change RemoteEvent to what you named the event to
_G.bestPokemon = "TapuLele" --just an example
event:FireClient(player, "bestPokemon", "TapuLele") --make sure that the key (bestPokemon) is made into a string!
There are some limitations however:
-This won't work for functions -This won't work for tables that both have numerical keys and string keys i.e
local tab = {}
tab[1] = "Hello"
tab.secondWord = "World"
-Metatables will be lost
-You can't reference an object that is only on one side (Such as a playerscript only visible to the client)
EDIT: If you want to go a bit further, you can do this process automatically using metatables. The only sacrifice here is that you can't store things directly in _G, but rather in a "subtable"
The first step is to make two empty tables on the Server.
--In a Script
local fake = {}
local real = {}
The "fake" table will be the table that is visible for us to edit (but we can't edit), while the "real" table is edited but not visible. How might this be possible? Through the use of metatables.
See, metatables allow us to make set and override functions that activate when you do "things" to a table. Such "things" include:
-Indexing (Referencing a value) an empty value on a table
-Setting an empty value on a table
Because these "things" happen only on an empty table, it's very important to keep the fake table empty.
Back to the point, we are going to give the fake table a metatable that will perform a bait and switch when these "things" happen. It will act as if it is the real table: the real table will be indexed instead of the fake one, and the real table will be modified instead of the fake one.
Here's it in action:
setmetatable(fake, {
["__index"] = real, --all indexes go to the real table
["__newindex"] = function(tab, index, value) -- on a new index, this function will activate
real[index] = value --the real table is modified with the correct value
--however, the fake table is left unchanged
end
}
You might be able to see now how the fake table gives us access to the real table indirectly. It also allows us to have functions occurr when we do normal operations, like setting a value to a table. Since that's the case, we can use this to automatically handle firing events as we set values. Here's the final product:
--In a Script
local fake = {}
local real = {}
local event = game.Workspace:WaitForChild("RemoteEvent") --Change RemoteEvent to what you named the event to
setmetatable(fake, {
["__index"] = real, --all indexes go to the real table
["__newindex"] = function(tab, index, value) -- on a new index, this function will activate
real[index] = value --the real table is modified with the correct value
--however, the fake table is left unchanged
event:FireAllClients(index, value) --update it in the client
--Notice that the function FireAllClients is used so we don't have to specify a player to send it to
end
}
_G.properties= fake --We make the fake table a property of _G. To make a value visible on the client, we just need to do one line:
_G.properties.bestPokemon = "TapuLele" --just an example. It automatically carries to all clients
-----------------------------------------------------------------------------
--Don't forget this part
--On the client (in a LocalScript)
_G.properties = {} --we give _G on the client it's own properties table to stay consistent
local event = game.Workspace:WaitForChild("RemoteEvent") --Change RemoteEvent to what you named the event to
event.OnClientEvent:Connect(function(key, value)
_G.properties.[key] = value
end)
--This says that when the event is fired, it will take the key and value it was fired with and set the desired value of _G.properties equal to the value. It's like _G.thing = otherthing
This discussion is preserved as it was. New answers, comments, and votes are closed.

3 comments
If you understand this, I can show you a way how to make it so you don't have to manually fire the function every time
I follow so far!
I updated it the automatic method