“do you not use specific class modules? Or do you just treat modules as classes without naming them as such.”
If you’re talking about OOP classes, I only use them when necessary. It’s not in my structure but I OOP-oriented scripts lying around somewhere. Like others said, OOP is not native to roblox so I try to limit its use but it’s not like it’s going to ruin your game or anything so I just use it when I feel it’ll be helpful. Most common use cases of OOP is when you need to apply common behavior to a lot of instances as you probably already know. I also mentioned you should know metatables but I was really only talking about functions closely related to OOP. Nevertheless, I do find that knowing a bit of metatables can actually be helpful for other parts of development. EX: you can use OOP + metatables to do something like
local Inventory = InventoryClass.New(Player,PlayerData)
Inventory + "Apple"
Inside the inventory class, there is an addition handler where if you try to add something to the class, then it handles it in a custom way, taking in the added parameter, “Apple,” and adding it to the player’s inventory. (__add metamethod)
Anyways, back to the topic of script organization,
I was actually looking into SSA, I was thinking it would be better to condense a lot of the module requiring, setup, and initialization into a singular place, instead of various scattered managers.
How I handle that is, I have a Players script in my structure under ServerHandler as you can see. Under it are modules such as “Data,” “Character,” etc. each submodule handles various tasks related to the Players. All submodules have the function “PlayerAdded” that is called when the main handler (Players) detects a new player. The Data subhandler handles all the data setup and management while the Character submodule loads the character and applies whatever is needed. The cool thing about this is that you can have sub-sub-handlers under the Character submodule that Handles Character-related stuff. To visualize:
Players
→ Data
→ Character
–>–> Accessories
–>–> Attributes
I also do acknowledge how others said that
If you don’t use a module for a shared value, it’s effectively useless.
And they’re not wrong. However, I feel that their approach is a bit black and white. What I like about module scripts is their ability to act as shared values or as standalone scripts. So what I often do is I combine them. In my previous example, my Data subhandler can automatically handle all data requests as a standalone script while having functions inside of it that can be called for specific events such as PlayerAdded to set up the data. To illustrate:
local DataHandler = {}
function DataHandler.PlayerAdded(Player)
-- setup Player Data stuff
end
Network.DataRequest.OnServerEvent:Connect(function()
--ability to handle independent data events
end
return DataHandler
You can do the same thing with normal scripts but they require remote functions or someting like that. But it’s just a bit harder imo, not to mention having nested scripts/local scripts can be messier than module scripts. That’s another reason why I prefer to use module scripts in my aforementioned structure.
I would say that once you find a structure you like, to just stick with it. It’s good to know how to work around various structures (especially for commissions) but having a structure you really “own” speeds up development for me since you already know where everything is and how the scripts work/connect. Until then, just mess around with different structures until you find one that feels right to you. A good way to do that is through working on different games and trying out their structures. That’s how I found the structure I like most.
Also, please don’t use ECS unless you’re building a huge RPG game with thousands of entities. It’s literally useless and will waste your time otherwise.
Good luck on your scripting journey! Let me know if you have further questions.