I’ve made a post about this before but I think it’s easier to make a new one to not confuse things further.
I have two metatables, for simplicity we’ll call them A and B. There are variables in A which I want to use in B. How would I get said variables from A into B so that they update every single frame (using RenderStepped, preferably). I am aware of rawget/rawset but I dont know if that works every frame - please clarify!
To complicate the matter, B must be required from A to hopefully avoid repeat scripts - I plan to add more metatables which need values from A (I would just require A in B and then pull variables out that way, but I can’t sadly because of cyclic dependency)
I believe it would be simpler to do something like:
local a = {
x = 0,
y = 0,
}
local b = {
z = 0
}
setmetatable(b, {
__index = a
})
print(b.x) --// prints 0
Make two separate tables A and B, then connect them using a metatable whose __index metamethod is just the table A. B would be able to index values inside A, but A would not be able to index values inside B. When a value in A is updated, it should be updated in B as well via the created metatable.
That would work in some situations, but once again the problem of cyclic dependency…
These two metatables are in separate modulescripts (for organization purposes). A is the “instigator” - it requires B so that B can run in the first place. B needs to get values from A, but can’t set A as it’s __index since it can’t require A or the two modules would require each other, i.e. cyclic dependency which luau hates.
It might be possible to have B set A as it’s __index in the ModuleScript for A while all of the code for B runs in the ModuleScript for B. I don’t know.
Then just remove the cyclic dependency. There should be a way to do the same thing without having to require A on module B or B on module A. In general, cyclic dependencies are bad in OOP and should be avoided.
Not sure if this is what your looking for, but it could be done like this?
-- Module A
local A = {}
A.__index = A
-- Constructor
function A.new(modules: Table)
local self = setmetatable({}, A)
self._Modules = modules
self.Name = "Module A"
return self
end
function A:HelloFromB()
print("B said Hello")
end
return A
-- Module B
local B = {}
B.__index = B
-- Constructor
function B.new(modules: Table)
local self = setmetatable({}, B)
self._Modules = modules
self._Modules["A"]:HelloFromB()
print(self._Modules["A"].Name) -- Should print "Module A"
return self
end
return B
Now that you have the modules script you would have one main script like so:
-- Main script
local Modules = {}
for _, module in pairs(Modules.Location:GetChildren()) do
if module and module:IsA("Module") and not Modules[module.Name] then
Modules[module.Name] = require(module).new(Modules)
end
end
Of course, you could make your own module system similar to the main script but add more methods such as :GetModule(), and what that would do is return the module from the modules table. Of course, since this isn’t needed but can be done to keep things clean, Hope this helps!