Module Scripts Inability to require each other?

I’ve been recently using a lot of modules to make repetitive tasks easier to code. I’ve run into this issue where if two modules require each other, the whole game seems to hang. My playerAdded script requires these modules, so I assume that’s why the game hangs. It’s just odd that I can’t have two modules require each other. Anyone have any solutions?

7 Likes

Module scripts cannot require each other because that creates an infinite loop of returning tables (or whatever you return with them) back and forth to each other, which is why the game hangs.

Your solution is to setup your module hierarchy differently. The way I think about it is two categories of module classes:

Access points:
Main functionality that the game uses to operate. This is where I use my remote event calls and listeners.

End points:
Utilities and modules that are self sufficient and do not need to require anything else. This could be things like a math utility module, a shop module, etc…

“But what happens when my end points need access to data in my access points?”

Pass your access point data to the end point in the function call

local stuff, _stuff = EndPointFunction(access_point_data, etc)

An alternate solution is utilizing BindableEvents and BindableFunctions to pass data, however beware as this can create clutter as well as limitations as you cannot pass metatable data through bindables.

14 Likes

This helps a lot. Thanks so much!

You should mark the post as being solved so that it’s easier for viewers to find, and shows the :white_check_mark: icon in the title.

2 Likes

Do you have any code sample, place sample?

Is this correct?

Send Data To Module.rbxl (13.2 KB)

Code

– Script

local Module = require(script.ModuleScript)

wait(5)

local Var1,Var2 = Module.Func('A',1)
print(Var1,Var2)

– Module Script

local M = {}

local Var1, Var2

function M.Func(...)
	print(...)
	Var1, Var2 = ...
	return 'B','2'
end

spawn(function()
	while wait(1) do
		print(Var1, Var2)
	end
end)

return M

– Output

nil nil (x4)
A 1
B 2
A 1 (x3)


@MrAsync you can have one central Module that never requires other modules but other modules require’s it for Sharing Data instead of doing

Heyo, I don’t actually recommend this, but I thought I’d mention that module scripts can require each other, just not immediately
Here’s an example:

local A = {}
local b = require(path.to.b)

return A
local B = {}
local A
spawn(function()
     A = require(path.to.A)
end)

return B
1 Like

I feel like @Crazyman32 's AeroGameFramework Plugin does exactly this (as in communication between modules, whether it is server > client, client > server, server > server or client > client), but this introduces a whole new framework that would be complicated if you are not experienced with it.

It’s really convenient and easy-to-use once you get the hang of it, though!

Wow, why didn’t I thought of that :+1:

That’s pretty good.

Why?

If you have two related modules with different hierarchical statuses, then the lesser module should not exert any control over the dominant module; thus it doesn’t need to require it.

Otherwise, if two of your modules both have the same hierarchical status, (and they must cooperate) then either you need to restructure the hierarchy or have them communicate indirectly through a third party module, which is used by both but does not require either.

Typically, you should try to avoid architecture where two modules are dependent on each other. See the Circular Dependency Wikipedia page for more info, especially the “Problems of circular dependencies” section.

Instead, you should try to follow the principle that @Fm_Trick mentioned.


If you have to do this, then it’s best to have a third-party load the modules, expose the modules to each other, and then inform the modules that the are ready. This is what my framework does that @AbiZinho mentioned.

5 Likes

Done! Thanks.