I’ve read several posts about this Roblox Library called Roact and how it’s similar to React JS, I however still don’t understand what Roact really is. I’ve seen other posts saying that they’ve used the said library in their plugin or interface for their game, so is this library more of the scripting aspect or interface design aspect? I have three questions to ask:
That video from Lucian is excellent. I wouldn’t be surprised if @LPGhatguy has some additional input he’d like to share in person.
Roact and Rodux are excellent tools that greatly aid development on larger projects. Facebook’s UI is built in JavaScript using React, and Roblox built the iOS and Android UI ports to Lua in Roact. The main reason they are so helpful is that they offer structured state management. Roact keeps your UI state (instance properties) in sync with your script’s data and Rodux offers a clean uniform way to update and track changes to that data (which may come from endpoints, user data, ext.). Since Roact and Rodux have been used in larger projects, many of the difficulties of actually integrating a new technology into an existing code base have been overcome. In addition since it is based on a much larger and more successful technology, its outlook is very positive.
To summarize how it works, Roact is similar to OOP but uses components instead of classes and wrapping instead of inheritance. When one page is updated, it updates all the components it uses behind the scenes and the update cascades down the tree as far as needed. Components connect to the Rodux store (which is like a client-side no-SQL database) and when any information in the store is changed the components update. In addition, components can send updates to the store at specific times to trigger updates. Roact strives to ensure that only the part of the page that needs to be updated is updated and that the update-cascades are kept into check. The user doesn’t have to worry about these updates at all and are in effect programming a static user interface, as described in the video.
Now, I heavily used Roact for a couple months last year and rewrote the core of it a couple times in different ways (once to completely remove the use of the Lua stack, another to heavily optimize it and even change the internal graph structure). None of my out-there ideas were actually committed to the repo but you will see my name under contributors for a minor improvement.
Roact in particular feels more heavy to me than it needs to be. Not just because everything is immutable and tables are being copied all over the place, but because Roact implements code reuse by wrapping. This is essentially like inheritance from OOP in reverse (and you all know my opinion on OOP…). Since the implantation isn’t baked into the language and isn’t compiled, you get multiple functions that are called simply to pass data from one place to another. It is very easy to enter a state called “callback hell”.
In addition you inherit all of the potential downfalls of inheritance like the Diamond problem in reverse: You have a simple text box component and two wrapped version of it, one that auto-resizes to match the size of the text and another that colors key words if present. To make a auto-resizing and keyword-highlighted text box component you can’t just wrap the two wrappers because each wrapper has its own internal-only copy of the simple text box. You have to either somehow make the previous two wrappers share the text box component (exposing internal workings) or copy the code from each wrapper into a third wrapper of the text box component.
Other than the problems above, Roact is a very powerful tool. Not without its downfalls like OOP, but excellent and worth a look into. I tend to favor tools that favor composition over inheritance / wrapping, like ECS. Here is a link in which I discussed a client-server networking model using ECS. It also contains multiple links to working ECS implementations, although not as robust or with the track record of Roact/Rodux.
What was your use case for Roact and Rodux? And by any chance would you know any games in Roblox that use these libraries? It just seems that these libraries would be too complex to be actually implemented in a game.
My use case was that I was an intern working on the home, games, and the start of the game details pages. I’ve also used it while working on an IDE UI in Roblox over my GLR parser for Lua. After spending some time on that project, I actually decided to implement my own ECS framework and use that.
While not touted, Roact/Rodux could also work for all game logic, however I wouldn’t recommend it unless you are familiar with the patterns and anti-patterns that are common when using them since it is uncharted waters. On the other hand, ECS emerged from the game industry as an efficient structure for game engines. Unity is heavily influenced by it, and I wish Roblox was more so.
I think they are a little different in that roact does the UI updating based on the Rodux state (which stores data)
They are used for UI
The documentation others linked is probably a good way to learn about how to use them
BUT, I think you should be very critical when deciding whether to use them or not
I’ve personally spent a couple of hours (at least 5 I’d say, but probably a lot more) trying to understand them from the Roblox perspective, but my only conclusion now is that they needlessly overcomplicate everything and make code harder to read and write
Though I’m also unsure if I conclude this because of a lack of knowledge or because it is truly the case
I believe your UI should [ranked in order of importance]
Get the job done
Be pretty
Be easy to update
Be easy to write
Be easy to read by others<-it probably doesn’t even matter most of the time though
So I think roact falls short (by a lot) because:
With or without roact you will get the job done
Roact will probably be (*will be) less pretty though because you are [currently] constrained to scripting the UI design instead of designing it in studio AND with roact you can’t do animations right now(?)
[I’m going to group this with 4 because they are similar]
Every single Roact example I’ve seen can be written in much less lines of code without the framework…I believe it unnecessarily constrains you: it forces a very abstract paradigm upon you
MAYBE (just maybe) Roact wins here if your teammates know of Roact’s standards and agree to follow them (but that’s the same as using any other framework!)
So I don’t use Roact for those reasons, I don’t really plan on ever using it either even if #2 is solved just because #3&4 are really big issues
I don’t believe in following bad standards because others do (#5) so its not much of an upside for me
But as I mentioned before, I don’t believe I’m an expert in any of this, I’m just someone trying to make his code writing as nice as possible while still making nice ui
If this is something you are genuinely curious about I think you should take some time to learn about Roact and Redux and then decide for yourself (side by side comparisons between ui written without roact and with roact could be useful for this)
I’d be curious to hear what conclusions you reach about them
From the perspective of someone who has started using Roact with no prior experience with React or really any declarative stuff, I can say that Roact most definitely is helpful but feels really limiting when you first start to use it.
I’ve found it doesn’t make the UI easier or harder but rather shifts where you find the difficulty. With Roblox’s vanilla UI you can use the editor and do whatever you want really easily, but later on it becomes a mess. With Roact initially making the UI is hard, animations are hard, debugging what isn’t working for what reason is hard. But while initially making the UI with Roact is hard, you end up with a well made reusable codebase which can be expanded on easily. Roact forces you to deal with technical debt from the start so it doesn’t plague you later.
My adventures with Roact has also shown me that the (what I think is) conventional way of making UI in Roblox is not a good way to make UI. Designing the UI in Roblox and directly using it is a fast, low barrier to entry, way of making UI but is not the way to properly do it. I’ve started designing my UI outside of studio then using Roact to implement what I designed. This keeps design vs implementation details separate, organises everything well and lets you make changes later easily. I believe this is the way it is done in the professional world too.
One big problem Roact forces you to come to terms with is animations. It feels like it prevents you from using animations, when in reality it’s preventing you from animating in ambiguous ways. For example let’s assume we wanted to fade in/out a menu when we open/close it. Let’s suppose this fade takes 1 second. What is supposed to happen if someone closes the menu then opens it again after 0.5 seconds? It’s half way faded out but now needs to fade back in? The typical way of handling this in Roblox is to just make a new tween but now a tween from mid animation will take the same amount of time as the full animation. It’ll look off, and there isn’t a trivial fix. If Roact is making it annoying to do something, it’s probably preventing a problem like this.
The main misconception I had, and I think many people have, is that Roact is meant to make UI work easier. It’s not. It’s meant to make it easier to implement, organise and expand a well designed UI codebase. That codebase might contain more lines, be more confusing or over complicate seemingly trivial problems but what you get, when you understand it, is beautiful and highly extendable.
This is the important bit. Making UI in Roact is, from my point of view, the worst part about it. I even asked that question about it in the RDC talk! It hasn’t gotten better since, but you just grit your teeth, grumble about it, and do it. In the end, I didn’t regret writing my UI in Roact. In the future, I hear this is going to get better as a Roblox engineer is working on a plugin inspired by Storybook which will let you preview components in real time, as opposed to sluggishly booting up your game every single time.