OMG! How is it that you cover such relevant topics for aspiring Roblox developers? I think, I need to find out how to do x and there is a tutorial for it on your channel. Keep up the great work.
Great tutorial! The base to create our own framework! Can you extend this tutorial with your best practices on how to communicate between client and server?
Super useful tutorial! A question I have is, using this structure where would I put events like .PlayerAdded. Would it be in a module script then required by the main script, or would the entire event just be in the main script itself?
I personally don't put anything else in the main script and everything goes in modules I hope to make a video in the future showing how to make a game using this style
@@5uphiPlease come round to this I’m very interested in a full tutorial of multiple things maybe even a live stream of continuous events or a Q&A where you program our ideas.
I absolutely love this structure and I'm implementing it for a big project now, but I'm wondering if it's possible to do this with remote events aswell?
Great tutorial! I’m curious, where did you learn how to code? I’ve tried but I’m not really learning anything from the places I’ve tried to learn from? Honestly the most about coding I’ve memorized are from watching your vids. So yeah, I’d love to learn to code.
Dude! This is so genius! I've been wondering what the use for _G was if modules exist, and also how to stay more organized and professional, and this kills two birds with one stone.
@@5uphi Oh wow! So it really is everything as modules. I have some separate scripts that I feel like I could keep that way, like one that handles all remote events for combat, and one that handles duels. Is there an advantage to make things like those modules other than making everything a module?
By using modules it allows other scripts/modules to access methods/properties inside them so by making everything a module it means everything can access everything
Hey I'm not sure what I am doing wrong but at 7:00 when you have everything loaded. My parts load and are placed in the exact place but I get an error that says ServerScriptService.Script:3: table index is nil. It's for the main script I'm not sure why it does this. It still works but why?
Happened to me, make sure is not Modules[Instance.Name] = require(instance) it should be like this = Modules[instance.Name] = require(instance) basically lowercase i because Instance cannot be used
How would I use this method with stuff like Promises and that class library inside of a Class script so that it doesn't make it look messy. For example I have it set up like this to make sure the class is initiated local Promise local Class local Inventory = {} Inventory.Initiate = function() Promise = _G.Promise Class = _G.Class Inventory = Class("Inventory") end
Aside from less header space, what's the benefit of storing all the module scripts in a global table, over just requiring them individually in any other script they're needed in?
There is only 1 benefit let's say you have 2 modules moduleA and moduleB if you require moduleB inside moduleA then moduleB can not Required moduleA Other then that it's just personal preference feel free to do what you think is best
Hey, so I have been scripting for years on roblox, but I am unsure to why you used module scripts instead of scripts for this instance. Should I replace all my scripts, that typically run when the server starts, with module scripts and load them with a loader script? Are there any limitations that this may come with?
So the main benefit to this structure is being able to control the order your modules run in and the ability to access all modules from anywhere To the question if you should replace all your scripts with modules. Using this structure is not mandatory if your happy with the way you currently have your project structured keep it the way it currently is but if your unhappy and after watching the video you like the structure I have presented in this video then give it a try maybe try it in your next project instead of replacing your current project I have not found any limitations to this structure to me feels very freeing when I code in this structure
@@5uphi Thanks for the response! I think I’m going to try adapting this method for my current project, I just grew up learning module scripts a bit differently and I didn’t ever think of using them this way. I’ve been watching a lot of your content and it’s been extremely helpful. Keep up the great work!
I see that a lot of people aren't really amused to use _G for this. I think a solution is that you can store the required modules in a loader script table and then pass that modules table to the Initialize method where you can store the argument in a nil variable in the module (Don't set the variable to an empty table at the beginning or it will give you warnings). This won't copy the modules table so you can modify parts of a module, and the other modules will be able to see those modifications. This also still allows two modules to communicate with each other.
Yer you can save all the modules inside another module then require that module to get the table of all the modules but there would not be any benefit to doing this if anything it would require more code and might be a tiny bit slower
@@5uphi Hello there! I just recently started working on a project that uses a scripting architecture like the one you provide in this video, and I decided to do a benchmark to test the speeds of this since you mentioned that my solution would be a little slower. What I did was clone every module and rename it to a GUID, and I repeated this 10 times (Each module being identical to the ones in this video). This left me with 3072 modules that needed to be required. I ran each test 10 times, and it showed that saving each module via _G and Initializing/Initiating everything took an average of 121 milliseconds. However, doing the same thing except using my method of saving the modules in a shared table only took an average of 48 milliseconds. From what I hear, _G is slower than local variables because of how the two are accessed. Local variables can be directly accessed from the current stack frame which is very fast and efficient. Meanwhile, _G has to look through a lot more places which can be slower than local variables.
Would you like to share your benchmark in discord my personal benchmarks don't have the same result accessing _G should be just like accessing workspace or math
@@5uphi nvm, I forgot to change a part of my code and it caused my scripts to loop though _G instead of the modules table. I also decided to replace the part in ScriptB with a Vector3 so the parts don't lag my game. I ran the benchmark again, and this time it showed that _G and my method took basically the same time to load at an average of 100 milliseconds (running each test 15 times).
Aren't module scripts already global? I'm confused as to why we are using _G when in the tutorial I watched it said _G is old and untrustworthy and module scripts are better? Maybe I'm wrong I don't know, I'm making my way through an advanced series now, and I feel like I've got a great understanding for how it's all working (just don't have too much experience on field yet). It seems like you're forcing the scripts to load when they're ready? That way you don't run into the _G variables not being loaded in time for use?
When you require the module for the first time the module runs and returns the table when you require the same module a second time you get a reference to the first table that was created on the first time you required it. in this video I'm saving the reference into _G so that I can get access to the reference without the need to require. It's almost identical in both cases you get a reference to the exact same table. There are only 3 downsides of using require that I know of 1) you can't require a module that required you 2) you have to type more 3) you have to keep track of what modules you have required But it's just personal preference if you feel more comfortable requiring modules at the top of your scripts then you can do that this video just shows how I do it
This is not true for actors when you require a module in 2 different actors the second actor will not get a reference to the original table it will run the module again and make a second table
When you say _G is old and untrustworthy what do you mean why would it be untrustworthy that's like saying workspace is old and untrustworthy it's just a global variable that references something. workspace references game.Workspace where _G references a empty table and math references the math library(table)
In ClassB the .Position function it is global because you did not set the __index of it right? (like you did in the ClassA). Nice video, thank you. p.s.: Did you tried the AeroGameFramework plugin made by sleitnick? it is a very good one that helps with all this organization and has all you need, been using it for years now
so ScriptB's Position function is just like a normal module function the only difference is you don't have to manually load modules all the time and we get access to the module using _G.ScriptB where Class is also a module that gets automatically loaded just like SctiptB but Class has a function called New and this function crates a new table and we set that tables metatable to the module table so what that means the table that is created in the new function if you try to access a key of the table that does not exist it will use the module table as like a plan B so when you use the Print function it first checks the table that was created in the New function for the Print key and as that table does not have a key called Print it will be nil and because its nil it will then check the metatable for the Print key and because it is found in that table you can use it and because every time we call the New Function all the tables created will all have the same metatable so i can call the Print function on classA and classB and the Print key will always go back to the same Print function that is stored in the same metatable so if i create 1000 objects using the Class.New() function there will only ever be 1 Print function that all 1000 class objects use you could also use the Print function like this _G.Class.Print(classA) this has the same effect as classA:Print()
Is there a reason to put module scripts in replicatedfirst over replicatedstorage or even startercharacterscripts for client sided scripts other than the loading?
Suphi Kaner, How do I remove your infinite terrain thing in my game? I don't hate it but it doesn't work for mine because of the way I made it work, I remove the script but the green stuff and the terrain thing still loads.
I just have a small question - would this work with inheritance used in classes? If yes how would I set up the Class2 which inherits value from Class (in the example) so it wont broke with requiring the Class module? :)
And btw I adore this setup, I am working on game rn that I have quite big plans on expanding later and after watching this I know I need to reorganize everything so it will be so easily accessed and structured like in this video so expanding the game won't be a nightmare in the future :) Great video!
Anything in serverscriptservice or serverstorage is not replicated to the client you can find this information here: create.roblox.com/docs/reference/engine/classes/ServerScriptService
@@5uphi That was my assumption too I've just heard some people on the devforum say that global variables like this can somehow allow code to be stolen even when they're server sided. Maybe they were wrong or I just misinterpreted what they were saying.
I would disagree that knit is more efficient but IV never used it but I think knit is more designs to handle communication between the client and server
Players.PlayerAdded event doesn't work for me, it prints "Here" but not the character name, why? local NewPlayerAdded = {} local Players = game:GetService("Players") NewPlayerAdded.Initialize = function() print("Here") Players.PlayerAdded:Connect(function(player: Player) player.CharacterAdded:Connect(function(character: Model) print(character.Name) end) end) end return NewPlayerAdded
@@root6132 it doesn't have to be. many speak badly of it and they have valid reasons for disliking it, but it's still a very convenient tool you can use in certain situations
Good tutorial although wouldnt recommend using _G since roblox documentation does states its 10 times slower id rather work arround it with something else.
@@5uphi Nevermind whatever I just said, while searching for the documentation I just found out this was changed or something, it says that _G is not slower than module scripts require.