Tweening with Roact

I’m trying to implement a button hover animation that tweens a TextButton larger when a player’s mouse hovers over it. Normally this is a simple task, but my UI is built with Roact (https://roblox.github.io/roact/), and I’m a totally newbie with the framework.

Would I use Refs to access instances directly? Or is there a better way to accomplish the tween? Additionally, if I change the properties of the TextButton, would Roact unexpectedly revert my changes by rerendering the button to match the properties specified by the Button Component?

9 Likes

This is kind of a weak point of Roact (and React!) out of the box.

One promising animation library is roact-animate by AmaranthineCodices. It’s based on React Native’s Animated, which I haven’t personally used but seems pretty cool.

Internally at Roblox, I’ve been working on something similar to Cheng Lou’s React Motion, creatively called Roact Motion. Right now it’s just a prototype, so it isn’t very friendly to set up and there aren’t any good docs. Eventually, I’ll flesh it out, since we’re using it in a few places!

Alternatively, it’s a good exercise to try to implement animations yourself. Just keep track of the current time or position in your component’s state, which means you don’t need refs! Hook into lifecycle events like didMount and didUpdate to start/stop your animations. Take a look at the Roact Motion codebase that I linked above, which has some great examples of how to do that!

You can try to use Roblox’s built-in animation tools like TweenService, but I’ve found that they don’t map very well to Roact. You probably won’t have issues with Roact reverting your changes now, but it’s possible you will in the future or in weird edge cases, so I would be weary of it!

11 Likes

wait, since when did the Roblox github have this Roact/Rodux stuff?

9 Likes

That makes a lot of sense. Thank you for the resources @LPGhatguy!

I noticed that AmaranthineCodices’ roact-animate uses TweenService under the hood, but I really like the public API in your Roact Motion. Are there potential performance concerns with using Lua to calculate each frame of the tween, as opposed to using TweenService (which I’m guessing uses C under the hood and uses fewer callbacks)? I plan on creating UIs for a production game that must run smoothly on low end mobile hardware.

And in general, should I be worried about performance if I follow React best practices? Are the many callbacks that Roact makes on state change pretty efficient?

In the case of animation performance, it’s not too big of a deal to run from Lua. Roact Motion itself ends up being pretty cheap, but it is calling render() (and thus performing Roact’s reconciliation step) every frame, which scales with the complexity of your components.

In general with Roact, performance shouldn’t be a problem. If you run into a case where it is, though, you have a few options:

  • Bug me (or open an issue on GitHub) with a specific case, and I can offer advice or figure out what optimizations need to happen to Roact itself
  • Extend PureComponent instead of Component, which relies on your data being Immutable. If you use Rodux, your data is probably immutable and this is a good first step!
  • Implement a custom shouldUpdate function to reduce the number of times your component re-renders. I wouldn’t do this unless you’re having performance issues and PureComponent didn’t help, since an improper shouldUpdate implementation can cause some weird bugs.
  • As a last resort, you can write regular Roblox UI code and embed it inside of a Roact component fairly easily, so you aren’t locked in!

We’re going to be using Roact and Rodux in more of our Lua code as time goes on – right now, that means the mobile app’s chat (not yet Roact), Xbox (partially Roact), and a few other mobile pieces here and there. All of these things are large and fairly complex, so we’re sensitive to performance issues and we’ll be working to make everything faster as we discover issues.

1 Like

We had sort of a soft launch in mid-December 2017. We’re still ironing out some of the workflow kinks, open source procedure, and responsibilities, so we’ve held off on making a big announcement. All of the repositories are up for accepting feature requests, bugs, and pull requests to resolve any open issues!

If you’ve got any questions about it, feel free to send me a PM or contact me via GitHub. I don’t follow the dev forums very closely, so I often miss topics about things related to me. :slightly_smiling_face:

2 Likes