GlobalFramework2
Into the SingleScriptArhitecture world! For games and plugins.
Since the post got way to long, I had to split this into 2 posts. This is part 1 of the GlobalFramework2 documentation, and part 2 is right here!
Warning (bug report)
There’s currently a bug with the installed plugins where they will crash your Roblox Studio after being active for 7-10 minutes. I have already made a bug report post right here, but we’re still waiting for a fix to these crashes. It’s a really annoying bug, and it will make the experience you’ll have while using this plugin really worse. Meanwhile, maybe try to spread the news about this bug, so it could get fixed faster. Thank you!
Also, the reason why these crashes happen is because of the recovery copies, when they are created and you have at least one plugin installed, so maybe also try to disable that feature for now.
To disable Studio’s Auto-Recovery feature:
-
Go to File → Studio Settings → Studio → Auto-Recovery;
-
Under Auto-Recovery, disable “Auto-Recovery Enabled”.
Intro
Hello everyone!
It’s me, nork24elec1!
In this post, I will present you the GlobalFramework2, a plugin that I started working on solo with a lot of passion and interest for the past 7-8 months, since the mid July of the 2024 summer, after having some problems with scripting on a game that I was working on. The game’s scripts were really unorganized, with most of them having repeated code and being scattered around all places in the explorer (NPC’s, tools, workspace models, etc.), which was really bad since as the game got more complex the debugging for the game started to feel impossible, as the was 0 control of what scripts will run first, and the way they loaded did matter. (plus I think I might have even forgotten about the existence of some scripts, which is really REALLY bad).
In this post, we will go over the 2 main architectures that scripters use to make their games, even if they don’t know it at first, those being MultipleScriptArhitecture (short stand is MSA, and this is the architecture that my game I’ve mentioned before uses, and the one that you surely also have used at one point, without knowing) and SingleScriptArhitecture (short stand is SSA, the point of what this plugin is all about, DOES NOT MEAN YOUR WHOLE GAME/PLUGIN WILL BE CREATED USING JUST ONE SCRIPT), learning about them, comparing them with their pros and cons, and then talk about which one is better to use and when.
After that we will continue on with SSA and then meet the GlobalFramework2 plugin that aims to solve all of SSA’s problems that make scripters not want to use the architecture, the biggest one being the lack of autofill/IntelliSense.
After the quick introduction, we’ll then learn about the both ways of how to install the plugin, the local way or the Toolbox way, again, then we’ll talk about the advantages and disadvantages of both ways, then after you’ve made your decision, you’ll be guided on how to install the plugin the way you chose.
After that, this is where the tutorial on the plugin will actually begin. We’ll learn a lot about the plugin, how it works, how to open its Window (or DockWidgetPluginGui, for those who know) where all the Gui’s placed, how to set up/remove/select/check the project components, all with just one click, about the 8 project components, what’s their purpose and how to work with them, then where to place all the ModuleScripts, some rules to keep in mind that really should not affect your scripting experience, about ModuleScript’s important checks from the top of the script, how to easily enable comment directives in your Modules using the attributes, about the plugin’s custom scripts highlights/analysis, what they mean, about the colors, that blue means good, red means bad and gray means information, about GlobalFramework2’s helpful Userdatas/UtilityModules that you can easily toggle on/off, where you can find them, about Stage and BuildInEvent Userdatas that you should really use, how autofill works, about the updates and automatic updates to autofill, old type solver and new type solver and how it affect autofill updates, how to create global types that you can easily use in every single created ModuleScript (as long as after creation its highlighted with blue by the plugin, meaning there are no errors), about cyclic code, that this framework lets you use cyclic code BUT YOU’RE NOT FORCED TO, ITS YOUR CHOICE, that there are no error types created if your created types depend on other types, an example similar to the raw SSA to get you going, etc…
So much to explain, I know, but grab my hand as well go over everything nice and easy!
Also, as a warning, please excuse my poor English, I’m not a native English speaker, and my native language is actually Romanian, since, well, I’m a Romanian. But still, I think you will understand my English really well, even if I’m not a native speaker. I’m sorry for repeating myself way to much in this post, or for having any typos. And also, due to this being my first dev forum post (ignoring the bug report) where I speak to you, the community, I have ultra anxiety while writing this, so yea… enjoy the post!
Also, another warning, if you, the user who’s reading this, is a beginner at scripting and doesn’t even know the basics of LUAU and of the engine, then you should skip this plugin for now and continue on learning the basics of LUAU and of the engine, as it’s going to be really hard for you to use this plugin if you don’t even know what script.Parent is supposed to mean when you see it in a script parented under a Part. After that you could try to give a chance to this plugin, since you know the basics and it should be really easy to understand how the plugin works, but if this is still a little bit too complicated for you to handle, then again, just wait, take it easy, practice more, and maybe slowly try to dive into the advanced side of Roblox Studio. The plugin will not go anywhere, so don’t hurry! However, I’ll still invite you to read this post, as some of the knowledge you’ll find here could help you to save time.
Ok, that’s it!
Let’s start!
The architectures
There are only 2 scripting Architectures, those being MultipleScriptArhitecture (MSA) and SingleScriptArhitecture (SSA). The truth is that, even if you don’t know it at first, whenever you’re scripting, you’re actually using one of these architectures. But what are exactly these architectures? How do they work? Are there any differences?
MultipleScriptArhitecture (MSA)
What is it?
I believe that every scripter has used this architecture at least once and should already know what I’m about to say. MultipleScriptArchitecture (MSA) is the development pattern where the game’s logic is created across multiple scripts (server and client) scattered all around the game, with each having their own set task. This is what new scripters start out with when they begin to script for the first time in Roblox Studio, and what most of beginners continue to use as they get better in scripting. The communication between the scripts is usually made using the bindables Instances. Here, ModuleScripts can also be used, mostly to store code (mostly in functions) to prevent code repetition, a really big problem that this architecture has.
Pros:
-
Beginner friendly. It’s really easy to learn and understand this architecture, as most of us (if not all of us) have started scripting while using this architecture.
-
Faster development. As most scripts don’t depend on each other, and due to the massive lack of coordination that would have taken time to manage in the other architecture, the development of the game is much faster with this architecture, as all you have to do when you have to code something is just to go there, do the coding, and you’re done. It’s really that easy.
-
Good for large teams. Different developers can work on separate scripts without conflicts, which also leads to faster development.
-
Errors aren’t really critical. If one script has an error in it, it usually shouldn’t ruin the entire game, as most scripts don’t depend on each other.
-
Good portability. It’s really easy to take the code that you’ve made (ex. Pathfinding NPC script) and reuse it in other projects.
-
Easy debugging. Since each script only handles a specific mechanic (and for like the 5’th time saying they don’t depend on each other), it’s easier to locate and fix bugs, thought the debugging might take some time if you found a bug in a script that has been cloned many times, since you’ll have to update each cloned script with the new updated source.
-
Easy to modify and disable features. You can remove a script to disable a feature without affecting the rest of the game (or better, just turn the „Enabled” property to false).
Cons:
-
Can become REALLY unorganized . It’s easy to lose track of created scripts, which will eventually lead to an unstructured and chaotic project. A strict organization system can be implemented to try and prevent this.
-
It gets harder to maintain in large projects . When you start to have dozens (or hundreds) of scripts, managing and keeping track of them and what they do can become overwhelming. The scripts being scattered all around the project makes this even harder. Again, a strict organization system can be implemented to try and prevent this.
-
More memory usage . Since every script runs its own environment, this can lead to increased memory consumption. For this, ModuleScripts can be used to store duplicated code to try to prevent some memory consumption and code duplication.
-
Encourages cloning . Speaking of code duplication, this architecture promotes the cloning of most scripts (ex. Pathfinding NPC script, KillBrick script, etc.) and scattering them in specific places, which is bad and can could affect the game’s performance. The CollectionService and Instance tags can be used to prevent this.
-
Changes can be critical . Imagine you are creating an obby, and you have to create a script for a Part that makes it to be a KillBrick, and then you duplicate that Part as many times as you need for the necessary KillBricks in your obby. Now let’s say that you want to make it that when the Parts are touched they turn red for like 3 seconds to better show the player that they touched the Part, well now you’ll have to go through all the cloned scripts and do the changes, which will take a lot of time. This is another reason why cloning of the scripts is bad. Again, the CollectionService and Instance tags can be used to prevent this.
-
Really critical dependency problems. For the most part, the scripts won’t depend on each other… but if 2 scripts do actually depend on each other then this is a problem, and that problem is even bigger if those 2 scripts are ModuleScripts, since as you might know 2 ModuleScripts can’t require each other, and if they try to do this then it will result in an error, that being the almighty cyclic module dependency error. In this case there’s nothing that you can really do, other that just trying to find another solution for the dependency to not happen, which is really hard.
-
Unpredictable code execution. What if some scripts must run first before other do to set up important things? This is also a really big problem that can lead to uncontrolled behavior in the game and maybe extra code. There isn’t a solution to this. (I think)
-
Increased complexity in communication between the scripts. Since the scripts are independent, the only way for them to communicate and share information among themselves is through bindables, where we have BindableEvents, BindableFunctions, RemoteEvents, RemoteFunctions, and UnreliableRemoteEvents (maybe?), which adds extra complexity to the game as you have to manage some sort of organization for the bindables (or maybe you don’t even want to make an organization system for them… simply just parent them under the scripts). Value Instances and Instance Attributes can also be used.
SingleScriptArhitecture (SSA)
What is it?
SingleScriptArhitecture (SSA) is the development pattern where the game’s logic is created using only a server script for the server-side logic, only a client script for the client-side logic, and the rest is just ModuleScripts, structured in Server, Client and Shared ModuleScript categories. The server script will require all the Server and Shared ModuleScript and store their return values in a place where all ModuleScripts will be able to access, like the „_G” global or the „shared” global, while using their name as the index, basically allowing for all ModuleScripts to know, easily share information and work with each other, making communication really easy, and then will manage the loading order of the ModuleScripts by usually checking if their return value is a table, then if that table has a specific index that’s a function, and the calling that function. The client script will do the same thing but with the Client and Shared ModuleScripts. Communication is also really easy, and the bindables shouldn’t be needed as much as in the other architecture (especially RemoteFunctions). The modularity of this architecture prevents code repetition. This architecture will make code organization and debugging more structured! It’s also considered to be better that the other architecture, and almost all popular Roblox games are using it. As the scripters get more experienced and learn more, they tend to switch, learn, and use this architecture because of the advantages it offers.
Pros:
-
Better organization. This architecture enforces a strict ModuleScripts organization that prevents scripters from scattering them everywhere, as they need to be placed as descendants of their specific containers to be required, which also ensures a clean and structured project layout.
-
Anti duplicated code. This architecture prevents duplicated „scripts” that do the same given task, as each ModuleScript name has to be unique and, again, they can’t be placed anywhere like in MSA, which helps with organization and also performance. Scripters will have to find other ways to handle Instances logic, like using the CollectionService and tags feature, ObjectValues, etc…
-
Very modular. Since all ModuleScripts know about each other, this fact makes for a really modular system, since ModuleScripts can share data that can be reused across different systems, like functions, making development more efficient, and encourages a better separation system of the ModuleScripts that keeps different functionalities independent, but interconnected at the same time.
-
Reduces memory used. The „anti duplicated code” and „very modular” pros also help with the memory management as well, since most code parts won’t be declared many times, like functions that do the same thing that might be needed to be declared just once, which helps with the memory used, reducing it down.
-
Controlled code execution. With this architecture you have the ability to control the code execution of your ModuleScripts, fixing the race conditions problem in the other architecture.
-
Cyclic module dependencies are not a problem. In this architecture, cyclic module dependencies are not a problem since they are resolved by the way of how the architecture works, so this means that you can use cyclic code among all your ModuleScripts, however keep in mind that this is still your choice if you want to have cyclic code, you’re not forced to use cyclic code.
Cons:
-
Harder to learn. This architecture requires a good understanding of how ModuleScripts work and how they will interact with their central script. The beginners who are used to the individual scripts for everything they make may struggle at first with the strict structured architecture. Also, understanding how code should be structured in the ModuleScripts can be a little bit confusing at first, because if it isn’t done right it will lead to errors.
-
No ModuleScripts autofill/IntelliSense. By far the best con out there. In this architecture autofill/IntelliSense for the required ModuleScripts is not available, which is also the reason why some people won’t want to switch to this architecture. There’s nothing that can be done against this problem. (or is it?)
-
Debugging is a bit harder. The lack of autofill/IntelliSense also affects the debugging in this architecture, as some features, like the „–!strict” comment directive that can be placed at the top of the ModuleScripts won’t work against the ModuleScripts, and will also take more time. But usually, debugging should still be easy here, maybe (MAYBE) even easier than in the other architecture, due to the modularity.
-
No exported types. ModuleScripts can’t export types to be used by the other ModuleScripts, which is similar to the lack of autofill/IntelliSense. There’s nothing that can be done against this problem. (are you sure?)
-
Harder portability. It’s hard to copy ModuleScripts and move them to other project since you will need to manage this system there as well, and if its managed then check for other things like the ModuleScripts’ names to be unique.
-
Some signals might now work. SSA may have a slower startup time if modules do heavy synchronous work (ex. loading large data dictionaries) which can bring some problems, like the PlayerAdded signal not firing for some players that have joined the game before the ModuleScripts had a chance to load (however this seems to only happen while playtesting in Studio).
What architecture should I use?
Use MSA when:
-
You’re prototyping, testing ideas and new features, or building a small game, like a fun obby, to play and mess around with your friends.
-
Speed matters more than structure (ex. quickly created scripts, with minimal planning, where code is mostly ugly, but it doesn’t really matter as long as it gets the job done).
-
You’re a beginner. You could still try to give SSA a try, though.
Use SSA when:
-
You’re developing a serious and scalable game (ex. RPG, FPS, simulator, etc.)
-
Long-term maintenance is a priority, since SSA’s modularity pays off as the project will grow bigger.
-
You’re working with a team.
Also keep in mind that you should choose an architecture from the start of the project and continue to script using that architecture. Migrating is still possible, but also painful.
More about SSA + meet GlobalFramework2
First of all, you must know that there are actually 2 ways of how you can set up this architecture, both of them having small differences. In the comparison header between the 2 architectures, we only talked about the first way of how scripters set up this architecture. The second way aims to solve the „issue” of using the „_G” global or the „shared” global as the way to store the results of all ModuleScripts, since some scripters see that as a bad thing to do (it’s really not, there are no performance issues, exploiters can’t break anything, it’s just some weird overexaggerating). For this, a ModuleScript, usually called „Loader”, is created in the ReplicatedStorage with the job of requiring all of the ModuleScripts and storing their results in a table public to that module’s return table. The server and client scripts now all they have to do is to require the Loader, then use the Start function of it (that starts to load all the ModuleScripts). Also, all ModuleScripts now have to require the Loader in order to know about each other. There will be no cyclic module dependencies because the Loader has been fully loaded by the time it’s required by the ModuleScripts. The Loader will also manage how the ModuleScripts code execution will work. It’s important to know about this second way because the plugin we’ll learn about uses the second way.
However, despite all this there will still be no autocomplete available, since the Loader tries to require a ModuleScript that also tries to require the Loader which will create that cyclic module dependency warning that will stop all the autocomplete, even if in this case it’s a false warning. This problem won’t be fixed anytime soon, as one of Roblox’s staff literally said 2 weeks ago that they don’t plan fixing this.
So now what, no autocomplete, huh?
Introducing GlobalFramework2.
What is it?
GlobalFramework2 is actually a plugin that will easily manage a SingleScriptArhitecture components (the second way) in your project with just one click of a button!
It includes all the raw SSA features + it comes with many fixes to the problems that the raw architecture has (the best fixes being that it solves autocomplete and also exported types, making them sort of global types) and comes with many great features, like the Userdatas/UtilityModules! This architecture also added support for plugins creation, which means that you can also use it to create plugins as well, with still all the features being included, none missing!
Does this sound great to you? We’ll, let’s learn how you can use this plugin, by first installing it.
How to install GlobalFramework2
There are 2 ways of how you can install this plugin, the local way, or the creator store (toolbox) way. But which one is better? Depends. If you install the plugin in the local way, then the plugin will always be available when you join a project, even if you switch accounts, which is a major advantage for those who have alternate accounts, but the downside is that updating the plugin will always take a bit of time, since you’ll have to get the latest source code then create a local plugin with that. If you install the plugin in the creator store way, then the plugin will only be available for the account that downloaded it, not for all of your accounts, which really sucks since you’ll have to download the plugin from all of your accounts, and it’s even worse if the plugin is not free… but the good side is that updating the plugin will be really easy, with just a click of a button, and auto-update can also be turned on.
So, decide in which way you’ll install the plugin. You can only choose one option, do not install the plugin in both ways! After that, I’ll show you how to install the plugin in the way you chose.
The local way.
You can either:
- Download this model, open it in a project, select the GlobalFramework2, PluginModuleScripts and StartPlugin Instances, then right click with your mouse, look for the „Save as Local Plugin…” option, click that option, then in the prompted window give your text file a name (you should name it GlobalFramework2, but it’s up to you), then create the file.
The creator store way.
You can either:
-
Click this link that brings you to the plugin’s page in the Creator Store, and get the plugin.
-
Open Toolbox, go to the Plugins category, search „GlobalFramework2” or my account name (nork24elec1), find the plugin, make sure it’s from me, then install it.
Part 2 is right here!