I’m about to embark on a new game, and wondering what is the best way to structure my UI code. There are two aspects about this I’m asking about.
1. Where I should actually locate my code
So what I usually do is have a script called UIElements, which will then require all the module scripts beneath it as functions passing a shared status. Each of these manages a specific part of the UI (i.e one might handle the leaderboard, another might handle the shop (the shop of course has further submodules)).
I don’t think this is the best way to do it, I’m curious how to see how you guys approach this.
2. UI Objects
I want to do things like AcceptButton = Button.new(Frame.ButtonObject) -- this would handle animations and the likes.
AcceptButton.Pressed:Connect(function()
--code
end)
I’m fully aware of how to implement something like this from a technical POV, I’m just wondering if anyone else has experience doing something like this, and what are the pros and cons of it.
I actually put LocalScripts in the Guis themselves, though I’ve wanted to condition myself to get away from that habit. I now typically strive to put Gui code in StarterPlayerScripts under some kind of controller in a MVC-like framework. I handle conditions for new Guis, respawns and whatnot.
I don’t make UI objects because that reinvents the wheel and complicates the UI creation process. It’s not needed, it’ll just unnecessarily bloat your code. If you want something like that, look into Roact. You can create your Guis with that and add your code in, well, whatever method you fancy.
Not too familiar with MVC frameworks. I’m more interested in the module scripts though, a well structured Roblox project should have very few, fairly short, LocalScripts
It will only bloat your code if you’re doing it wrong. There will be an additional one line in your variable declaration, and then functionally everything else works pretty much the same. Its just that you don’t have to declare the animations over and over again, and if you want to do something like allow users to change the colour of the buttons, you have a centralised place to do it from.
It also provides for changing the buttons per device, e.g on Xbox you can have the Button.new function change it to instead be “Press [A] to accept”, and Pressed (as used in my example) would fire when this was done
I only use one LocalScript that acts as a bootstrapper. Every piece of code exists in a ModuleScript. One of my favourite frameworks is Aero Game Framework which practices this amazingly.
I mean, I guess? If you have more than just the creation process behind it, then I can see use for objects to streamline behaviour. I’m just not quite conditioned to doing it because I don’t see much of a point. If you have your own respective use case for it though, that’s alright.
In that case, you can do both, unless that’s exactly what you were looking for in the first place. Everything from your constructor module to the code that makes the Guis function can be placed in StarterPlayerScripts and you can have different modules controlling different things.
My structure follows the convention that you said isn’t the best way to do it: I think it is. Having a super controller manage other controllers under it is actually cleaner than you think. Your idea of a UIElements script that requires modules beneath it is fine.
There’s not much more cleanliness you can get out of systems like this. Just make sure that you make use of modules to their maximum extent. For example, I typically don’t have any code running in the main thread of a ModuleScript anymore: I always have it return a table with something. Most things happen in functions and such. With Aero, specifically an Init and Start function for controllers.
I don’t put the LocalScript inside a Gui, I put it in StarterPlayerScripts which is a non-resetting container canonically intended for client-side scripts. It’s sort of like ServerScriptService but for the player and it only accepts LocalScripts.