Hi, i’ve been recently wondering how big games manage module-based games.
I mean games like ‘Ink Games’ Where the game place requires modules that handle stuff like cutscenes, the current phase of the game, timers, players overall, etc.
I tried scripting an actual big game, but i’ve got into a little roadblock.
Let’s say i have 2 scripts. The Game Manager and Phase Manager, they both need to require each other to get the methods or variables from each other.
I’ve got around this problem by just passing in the GameManager instance to the .load functions in other modules.
But with that solution there’s another problem. Types. I can’t get the GameManager class without requiring it. The only way i found to fix that is by having another module just for types, but by doing it this way it’s way harder to script since if you want to add a function you have to manage 2 scripts at once.
If you’re wondering how my modules look, here’s an example:
--!strict
local GameManager = {} :: GameManager
GameManager.__index = GameManager
export type GameManager = {
__index: GameManager,
new: () -> Game
--other methods
}
export type GameProperties = {
--game properties here
}
export type Game = typeof(setmetatable({} :: GameProperties, GameManager))
function GameManager.new()
return setmetatable({
--properties
} :: GameProperties, GameManager)
end
return GameManager
There has to be a better and correct way of doing this.
Important Notice: I. Need. Types.
Before anyone points it out, I’m not making another version of ink game…
Avoid cyclic dependencies between modules. They create fragile code, make debugging harder, and often lead to unexpected runtime issues. If two modules depend on each other, it’s usually a sign the design needs to be refactored into clearer, one-way dependencies.
Types are often kept in a separate module, might be a tiny bit harder to manage but it’s a million times better than trying to get around cyclic dependencies.
Try to design your modules so they never require the main script (or each other) again. If a function in one module needs access to something from another, pass it in as a parameter instead of creating a cyclic dependency
Yea, passing the instances as parameters was my main go-to solution, but again it’s the types, having each type in a seperate module is hell. Thats why i wanted to avoid doing that, if there’s no other better solution than this, then i guess i need to stay with it for now
Yea i already know about the cyclic dependencies, im just trying to get over the fact that i need to redefine the types from another type module, it’s just annoying
Just have some “Types” modules. This is a commonly followed pattern. Maintaining 2 scripts at once may be time consuming, but it’s worth it, and was always worth the effort. Unless you really have problems with managing scripts.