Hello, this is rather a general game development question, would ask this on devforum if I could bother getting accepted in there.
What would be the best way to structure scripts on a major project, trying to make as much things as possible in one big script, or making multiple scripts each doing something else. If so, how would you make all those scripts communicate with eachother, possibly making one big main script and the rest just modulescripts?
For example, you have a script that holds a table with player data, and you would need to reuse, have access or change that data in a script or part of code that could for example handle a shop. Would you put that part of code into the main script, or use a different script and make those scripts communicate with eachother, if so then how.
Does a major game like Phantom Forces for example, which definitely has lots of scripting handle majority of stuff in one big script, or rather separates them in multiple ones, ones that need to communicate with eachother.
This allows for easy debugging in the future. Never write sloppy code and expect to be able to read it 2 months later; you won't. The explicit point here is to remain organized, and Roblox provides you with a few tools to do so.
require
it from within the script near the top.One of my biggest criticism towards Roblox as a game development platform is how it doesn't push people to write code like it'd be done in the "real world". You can still do this. Sadly, there isn't a proper repository system nor a standard on how modules should be written and distributed.
You should only have one script for each end -- the server and the client. That script is responsible for the initialization process. Dependencies initialized by the "main" script then depend on other dependencies, while making sure cyclic dependencies do not happen. This is a great talk (1st of 3 parts) regarding dependencies and how to design the structure, and although it's presented in cppcon, it still applies to all projects.
Here's the structure for my most recent project.
And here's the dependancy tree associated with it.
The project is still so early in development that the tree will get a lot bigger, which just shows how large these programs can get. That's why it's really important to keep track of what's going on.
For example, here's what my "main" script looks like on the client:
local ReplicatedFirst = game:GetService("ReplicatedFirst") local get = require(ReplicatedFirst.get) -- local function init() print("Client initialization started") local startTick = tick() for _, module in next, get "all" do coroutine.wrap(function() if module.init then module:init() end end)() end local endTick = tick() print(string.format("Client initialization complete, took %.4f seconds", endTick - startTick)) end init()
The server "main" is identical except it requires the "get" module from the ServerScriptService.
"get" is a function similar to other languages' include/require/whatever functions. The reason I'm not using Roblox's require function directly is because with my own function I can add extra functionality to it.
Here's an example code snippet of my "cameraInputManager" module, which also shows the usage of "get":
-- Responsible for feeding input to the activated camera local get = _G.get local camUtil = get "sys/camera/cameraUtil" local input = get "sys/inputWrapper/input" -- local camInpMngr = {} -- local function rotateViewpoint(inputObject) if inputObject.Delta.Magnitude ~= 0 then local camera = camUtil:getCamera() if camera then local pitch, yaw = 0, 0 local delta = inputObject.Delta * -1 pitch = delta.Y / camera.viewportSize.Y * 5 yaw = delta.X / camera.viewportSize.X * 5 camera:addPitch(pitch) camera:addYaw(yaw) end end end -- function camInpMngr:connect() input:createListener("inputChanged", rotateViewpoint, Enum.UserInputType.MouseMovement, Enum.UserInputType.Touch) end function camInpMngr:init() self:connect() end return camInpMngr
So in short: have one script per client/server and design with modularity (use functions properly) and dependencies in mind. Many people put way too much stuff into one function block which should not be done as that's not modular design.
There are quite a lot of results covering these topics on the internet and you should really look them up as they're way too wide to cover here. Just because they aren't done using Roblox or even Lua, doesn't mean it won't apply to them.
I'm not entirely sure what type of Game you're going for but I occasionally write, highest I got to before taking a break was 302 lines, quite a lot to debug so pace yourself.
It's actually hard to sit down and try to think about how everything is supposed to come together, especially since you don't exactly know what method of Scripting you're going to use, so I'd ultimately suggest this order as best for basic GameScripts, yet there are more things to add, even I don't know too so just try anyway and see how it goes
Variables
Functions
Events
Configurations
Conditional Statements
These categories apply to each other though so it really doesn't matter which way you put it or when you use it, except for the first 3