Issues with organizing code

I am creating a single player game inspired of “Get a snack at 4 am”, I am having issues organizing and using Modules, RemoteEvents and Scripts.

I think that I am not doing it right.

This is how it looks:
Captura de pantalla 2024-06-27 002354
image

This is the MoneyModule
As you can see in this example, there are some functions, but I don’t think this is done correctly.

local module = {}
local gs = workspace.GlobalSounds
local rs = game:GetService("ReplicatedStorage")
local ServerModules = game:GetService("ServerScriptService").ServerModules


local Money = {Tix = 1, Robux = 5}

function module.PickUpMoney(player, part, money)

	part:Destroy()
	gs.MoneySounds:GetChildren()[math.random(1, #gs.MoneySounds:GetChildren())]:Play()
	player.ValueFolder.Robux.Value += Money[money]

end

return module

Before using Modules i used RemoteEvents for all functions, and it feels the same.

If someone can give advice or suggestions, please reply.

1 Like

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.

1 Like

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.

1 Like

So I can replace the events with a module?

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.

1 Like

Thank you, now I understand it better.
I have another question, it’s better to store all functions in one module or have various modules like i have?

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.

1 Like

I feel like the amount of modules is excessive. I don’t know what game they are making, but a whole module for doors seems unnecessary.

1 Like

You are right, the problem is that I don’t know where to put it, like in what category.

You could make actions a module script and have other dictionaries inside for each former ModuleScript that have their functions.

1 Like

image
You mean creating a Module with all functions and add tables to it?

1 Like

Yeah, and that would also let you reuse code if you need between modules.

1 Like

Seems like a good idea, I will try it tomorrow, thank you.

1 Like

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:

– CombatFolder
------ CombatService.lua
------ CombatConstants.lua
------ WeaponsList.lua
------ etc

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.

2 Likes

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
2 Likes

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.

2 Likes

Thank you all for helping me, have a nice day everyone!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.