As I begin my first “real” attempt at creating an organized and manageable codebase for my GUI, I am curious how people approach this part of programming on Roblox in a sane manner?
My server-sided code is OOP with one central server handler scripts that connects a growing list of module scripts that handle various aspects of my game. I tend to avoid placing scripts inside game objects as a philosophy, I achieve this through the use of CollectionService and other fun techniques.
As I begin to think about making my GUI with similar philosophy, I come across “problems” and I wonder what others do in these circumstances.
It seems obvious that the “easiest” way to handle things such as clickable buttons is to have the code right inside the object itself. I am ok with violating my philosophy above, but is this the best way? Can I stick to my guns here? Using CollectionService seems like a bad fit since many buttons will be the sole owner of a tag and thats not much of a collection, is it? Or maybe this is ok?
How do you manage state of the GUI? which windows should be displayed when? has anyone im-implemented a state engine that allows the local machine to simply read the state from something like a ValueObject in ReplciatedStorage and then display the GUI according to the listed state?
Just curious how people approach this, thanks for you input!
I was working on a project for a friend who wanted all the GUIs scripted. I normally avoid them like the plague, but I obliged for my friend. I like having neat and orderly code design, so I did some research on some alternative paradigms to the heavily event-driven design of most GUI code.
So I came upon this trend called finite state machine UIs. I believe computer science majors learn about finite state machines in college. Basically, we often model the state of a GUI using Boolean variables and conditional statements, but this can get messy. Finite state machines are a much tighter and more robust way of modeling, well, something with a finite number of states.
If you design a finite state machine correctly, you avoid a lot of headaches in event-driven programming that come about from convoluted conditional statement trees and handling unexpected inputs. In a finite state machine, all of that information is made implicit: the inputs that are valid for the current state, possible state changes, and what the machine outputs in response to input.
I should say that I never finished my friend’s project. As it turns out, finite state machines are quite rigid and hard to grapple with theoretically. Their rigidity is what makes them robust, but this also makes them pretty inflexible when it comes to performing more complicated tasks. There are certain things we can do to make them more useful, e.g. unions and Cartesian products of machines, but by nature finite state machines are somewhat abstract, so I found that it took up a lot of my brainpower thinking about how best to modify the finite state machine concept to suit my needs. I feel that this is the main tradeoff when using any abstraction in programming: cleaner, easier-to-maintain code, at the cost of increased difficulty in the process of design.
Anyway, you might be interested in finite state machines, though I should warn you that they can be deceptively complicated.
I have looked at it (Roact), but it honestly seems overly complicated for use in Roblox. Besides I dont want to learn a whole new paradigm here, and I also want to be able to do some GUI building in Studio, making everything by code alone seems tiresome.
I personally have a single local script inside of my guis that just gets gui data from my modulescripts, and then acts accordingly, like creates buttons or changes items in the gui. Hope this helps :3
For mnaging something like on-screen buttons that open additional GUI windows, I was thinking about something as simple as having a class that initializes for the player on joining and it then create a StringValue object and connects a Changed event to it. When the players click a button on screen, that sends a RemoteEvent to the server and changes the value of that object to reflect the desired state.
The client is listening for the Changed event and when it occurs, it will close all open gui windows, then opens the one according the state inside the ValueObject.
Does anyone do this? Seems simple enough but I am in new territory for myself here.