State and UI management

I have an increasingly complex application and the imperative code monolith / labyrinth I’m building is making me nervous. I want to introduce some good patterns. With most html apps I would use something like Preact with Redux and leverage the react-redux library with its Provider, and connected components via the connect(map_state, map_dispatch) or hooks to handle updating the UI when the state changes. What are good patterns / libraries to use in BabylonJS?

I may also include a pubsub where performance was important (as redux can get a bit slow if you are intermittently releasing 100s/1000s of actions a second) and or a state machine for complicated parts of the application.

I have found this question which kind of touches on it: Babylon.js project start-organization and I have found this demo: Babylon state machine demo with xmachina I have also found this new issue: Visual State Manager - Beta · Issue #12575 · BabylonJS/Babylon.js · GitHub

I was wondering if there is any tutorial page on state management, or any other demos, for example using a pub sub or a state container like redux that hooks into a system where you can declare the components / UI that should render when the state is in certain conditions?

cc @RaananW and @brianzinn for the React part.

First - thanks for the PR on xmachina - it’s merged! I think state machines and general state management (ie: Redux, zustand) are designed to meet different needs.

I have found that Redux (in combination with redux-saga) can work well in turn based games and configurators and is really testable, but becomes more problematic in higher frequency updates to state that flows through the react renderer. I don’t really like all the boiler-plate or providers and it won’t cross renderer boundaries with a bridge since it uses the context. Keep in mind that you can update outside of the React renderer, much like react-spring does animations and it performs well.

The xmachina React demo that you link to has a hook that pushes the State machine updates back to React. It uses a pub/sub mechanism derived from (a copy of) Babylon.js observables:
xmachina-semaforo/useMachina.ts at main · brianzinn/xmachina-semaforo (github.com)

^^ You can see the subscribe mechanism pushes to the useState hook and magically things just work.

I’ve been using Zustand state management lately instead of redux - it has also slices (like redux selectors).

Lastly - I can’t speak of the VSM, but I’m sure Raanan can. I did look at building a 3D implementation of an xmachina State Machine visualizer using a Force Directed physics engine I wrote (wammo) that works in Babylon.js and solves in iterations and can build the visualizations of State Machines on the fly - I did an experiment a couple of years ago using Dagre (2D force directed graph) there is a demo here (only 2D directed graph layout and does not solve iteratively with render loop):
brianzinn/babylonjs-directed-graph: Directed Graph testing in BabylonJS (github.com)

Certainly an area of interest for me these topics - mostly I haven’t been able to make much time recently to work on these fun side projects :smile: xstate has an excellent ecosystem for state management and visualizers.

3 Likes

Thanks! The demo code you linked to showing the xmachina <-> redux/react syncing mechanism is interesting.

I am currently planning to use BabylonJS for all the UI and not using React for any of it.

I am also planning on using xmachina for particularly complicated parts of the logic. For general “which UI window is showing” I am currently planning to use redux and use a lightweight “connector” I have written because I think there will be many possible transitions available and I don’t want to put them all into xmachina… although I also have in the back of my mind that I might write some code that allows me a higher level way to define all the transitions needed and that produces the object to instantiate the xmachina state machine.

This is the “connector” code I currently have to allow me to use Redux with BabylonJS’ UI: sustainability-sims/connected_component.ts at ae7e91423250fb4046b04c05eecdba583be0561c · centerofci/sustainability-sims · GitHub

And a demo of it being used by the top level “scene creator” and the lower level component implementing the connector.

sounds like a fun project - let me know if anything can be added to xmachina to support your scenario. it’s definitely designed with game design/flow in mind and not React specific.

I think the Babylon.js GUI goes really well with state management together with React - it’s hard for me to write that imperatively anymore. ie:

1 Like

Thank you @brianzinn I will definitely bear this in mind.

Yes, that demo looks great. I tried adding react-babylonjs to my project but got stuck when the JSX.IntrinsicElements typings errored, e.g.:

I tried running the demo typescript app you’ve also kindly provided but I hit an error with that. I will definintely bear your project in mind though… looks really useful! :smiley:

As an aside do you know if react-babylonjs plays well with preact? I like to keep my build sizes as small as possible as they can already get pretty heavy with the models that are loaded. Thanks!

Unfortunately tree-shaking isn’t working right now on react-babylonjs (the declarative react renderer), but it does on babylonjs-hook NPM. I haven’t managed to find the time to make a permanent solution (dynamic loading or dynamic registration) - I think the build size will be disappointing, but on the other hand babylon.js is small compared to even some single textures.

Separately, I have not seen that issue with JSX.Intrinsic elements. Maybe if you reload vs code it will bring in the ones added by the library. You should get intellisense on all of the camera props.

1 Like

Hey thanks again @brianzinn I know this is slightly tangential to this thread but thought I’d post that I have found a partial solution to problem with JSX.Intrinsic elements in preact.

I could always publish both - I don’t mind as I believe that like typings those are erased at build anyway. Let me know if the SO post has any ideas. :smile:

Thanks @brianzinn ! I tried a couple of times to get it working with preact but it was just spinning and never finished rendering so I am just going to use react instead now :slight_smile:

1 Like