What exactly makes you think this isn’t the right way of organizing your code? Obviously I’m not familiar with your entire codebase but from what you’ve shown here, I don’t see anything wrong with it.
I don’t know how to organize the local side, in the first image there are RemoteEvents and I don’t know if it’s better using Modules.
In general I am very lost and it’s the first time for me scripting modules, I made this post because i’ve never scripted like this and it feels strange.
I just need to see how the other scripters use Modules and Events
Are you referring to the client side code? You can have ModuleScripts on both the server and client and communicate any necessary information via RemoteEvents.
Well RemoteEvents are used to allow the server and client to communicate with each other. ModuleScripts are used to organize and separate code into different “pieces” that can be shared within the code base. Just like how you did with MoneyModule. They help avoid code duplication and improve scalability and maintainability of the code. ModuleScripts and RemoteEvents serve different purposes.
Not necessarily. I feel like you’re confused on what module scripts are and what remote events are. Remote events let you send data from the server to client and vice-versa. Module scripts don’t let you send data from server to client and vice-versa. You can place a module script in a location where both the server and client have access to, but they’ll still only have their own version.
If you’re only reason for using remote events was to ensure the client has the same data as the server, then yea you can probably replace that remote event with a module script that contains the data you want. That way, both the server and client automatically have the same info.
It’s important though to understand that if you change values in a module script on the server, those changes won’t be reflected on the client. Likewise, changing values in a module script on the client won’t be reflected on the server. This is where you’d use remote events to send information between server and client.
Generally people (myself included) will have various modules each with their own related code. It’s easier to maintain and build off of when you do that instead of having everything in one file. Ultimately though, it’s a personal preference and if you have a good reason to put things in one file then by all means do that.
Our project is built almost entirely on modules. We use a single local and server script to bootstrap the game. We separate our modules by feature. For example, if I’m making a combat system, my structure might look something like this:
Also, remote events are essential. We use them to communicate between the server and client all the time. There shouldn’t ever really be a scenario where you would have to pick between either using remote events or module scripts; they have different purposes.
ModuleScripts:
A place to store reusable code that can be accessed by other scripts/modules. They are great for decoupling your codebase and separating concerns.
Remote Events:
Used for one-way communication between the server and client. Very essential.
I have a single LocalScript that initializes all the modules on the local side, and it’s during this process where connections are made to remote events.
Simple coins GUI
-- The server tells the client how many coins the player has, then this module
-- updates a GUI with that amount.
local CoinsGui = {}
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local text = Players.LocalPlayer.PlayerGui.UiContainer.TopBar.Coins.CoinText
local function updateText(amount)
text.Text = amount
end
-- This function is called right after this module is initially required.
function CoinsGui._init()
-- all remote event connections for a module script are made in the _init function
ReplicatedStorage.Networking.CoinsUpdate.OnClientEvent:Connect(updateText)
end
return CoinsGui
In my framework, the _init function is used when you want some code to run after the module has been required. This function is called by a LocalScript that requires all the modules in the beginning. Below you will see an example. This is where you can put your remote event connections. I put all my event connections into the _init function at the bottom of my modules so that I can instantly see what kind of connections are made in a module.
Simplified example of the LocalScript put in StarterGui
-- Wait for client to load so that we don't have to use WaitForChild in our GUIs
if not game:IsLoaded() then game.Loaded:Wait() end
-- Clone GUIs (that are now fully loaded) into PlayerGui
local cont = game.ReplicatedStorage.UiContainer:Clone()
cont.Parent = script.Parent
-- I personally keep my client modules in a folder and then clone the folder into PlayerScripts
local core = game.ReplicatedStorage.ClientCodebase:Clone()
core.Parent = game.Players.LocalPlayer.PlayerScripts
-- Put all client-side modules into a table so that we can call the _init function on them.
-- The same thing happens on the server.
local modules = {}
for _, i in ipairs(core:GetDescendants()) do
if i:IsA("ModuleScript") then
modules[i.Name] = require(i)
end
end
for _, i in pairs(modules) do
-- not every module is going to have an _init function, so we check for that
if i._init then
i._init() -- RIGHT HERE is where we make all our event connections
end
end
I see no problems with this personally. We do something very similar, We have an optional Init() and Start() method on each module that gets ran one after the other. In those methods is where we establish our connections same way as you do.