Tool Spotlight - Fluxity Part 4

by Steve Halliwell · January 20, 2025

We’re in Part 4, of looking at our tool Fluxity. In the previous parts we’ve discussed the overview, the pros and cons, and some learnings along the way. In this entry we’re going to look at what we see as the next steps in advancing Fluxity, building on top of what it provides, and the surrounding systems it prompts.

Rx

If you are unfamiliar, this is Reactive Programming, the latest project for unity, and a more intro explainer. Even that intro explainer is still a lot. We’d like to be able to subscribe to an observable change, filter and recombine that data, re-expose that as a new observable (or stream of events). This would let us use simple functional composition in scenarios such as: notify a frame later, notify when a slice of state has actually changed, notify when all of a set of states have changed, notify of the delta between the last two values, or notify with the average of the last 10 values, etc.

The exact approach here hasn’t been investigated, we’ve been a bit busy. But the motivation here is to lift some of the minute details of dealing with state change up into a more reusable, functional style. The benefit we seek are shorter, simpler, more comfortable presenters, effects, and FeatureObserver interactions in systems. A cursory look over some of On Point, we’d refactor and simplify half a dozen presenter style objects that presently hold some slice of previous state and only propagate on specific changes on their slices or specific subsets of an enum value in the state itself. It would also allow us to remove a base class we find ourselves using quite a lot, SingleFeaturePresenter.

Tools improvements

We have a number of editor windows that give insight into the internals of Fluxity and its operation. These are all pretty barebones right now, they are certainly useful but as projects grow they get a bit cluttered. As a starting point, they all need better search and filter logic, so you can better ignore parts you aren’t trying to reason about from creating noise in the view. This is especially true of the dispatch history, where we’ve found ourselves reworking parts of the code so the history is cleaner. That change was for the better but it shouldn’t be a requirement for observability and debugging. Similarly it will be nice to be able to filter the list of options in the stores view by the variables names and values on projects that end up with many many things in stores. Another minor developer QoL improvement here would be adding ‘go to code’ right click feature. Presently we often identify the area of interest from the window then switch to the IDE and search for that type or function, which is a bit cumbersome and sometimes misleading. We should be able to make Unity open the right file from the context you have in the fluxity editor window in question.

Systems

In the ECS sense of the word, not specifically the Unity DOTS and Entities packages but in the more general way, a la https://www.youtube.com/watch?v=W3aieHjyNvw. Moving away from each object running its own updates etc. and towards a central system that runs that specific behaviour for all objects that need it, makes a lot of sense generally but has nice synergy with Fluxity. We end up storing things in archetype style collections for basic data sharing in the first place. We’ve touched on this in previous entries, but the ‘forward looking’ part of this comes from a lack of simple bridging between existing GameObject-Component logic to System-Collection logic. There’s lots of these type of midway steps between full on Unity ECS that we’d need to look into before we throw our hat into the ring too, but the key things that would be of value there would be:

  • Orderable systems
  • Always running
  • Mutable per system data (e.g. bulletSpeed, fadeOutTime, maxHealth)
  • System messaging (probably queued)
  • Straightforward archetypes by component (or other existing gameobject - element)
  • Support multithread (jobs)
  • Appears in profiler
  • Editor tooling that allows GameObject like workflows to continue

Short Term

There’s a number of features and QoL improvements that are in front of us;

  • Increase Minimum supported Unity version
    • Rework dispatching to support structs/value records as commands
    • Get access to ‘with’ statement
    • Remove a lot of our ‘by convention’ patterns in setting up state
  • Simplify reactivity
    • Allow straightforward response to command dispatch, sometimes you just care about the command not the state context
    • Allow lambdas as Effects, often writing 1 or 2 liner effects that end up their own classes with DI etc.
  • Make Flume DI an option not a requirement
    • Allow at will requests for state without resulting in DI exceptions
    • Allow use of other Unity DI tools.
  • Supply Generics/Code Generators to ease the set up of extremely common Features
    • E.g. we often have multiple features that are a List with ‘add’ ‘remove’ by list commands and a ‘reset’
  • Remove the noise and clutter caused by a state that gets modified by command every frame.
    • We don’t want a dispatch every frame that just invalidates and replaces the entire - state every frame
    • A common example of this is a round timer, you want it to update based on tick, not datetime, but not dispatch a ‘SubtractDTFromRoundCommand’ every frame where the game isn’t paused. But making it a mutable object inside a state, means we don’t get the change handlers called by the feature.

Longer Term

Now we get to the real meat of it. Where do we want Fluxity to be years from now? How much more do we need Fluxity to do? How successful is it really? Do we want to keep investing in it? Is it actually solving our problems? Is it speeding us up in a meaningful way?

Alright, quick gut check on those kinds of questions.

  • If we add much more to this, it’s not Flux anymore, it’s something else.
    • So we would either shift it to a framework or build out utilities that slot optionally on top of it. The later seems more attractive as it feels more composable.
  • As per previous entries in this series Fluxity certainly feels like a net positive.
    • It is helping, it is speeding us up, it is making parts of the game more straightforward.
  • We probably don’t want to make large time investments.
    • Most of those short term improvements are just QoL, which is nice but the ‘time in’ vs ‘productivity out’ has probably passed some point of diminishing returns.
  • Avoiding a full recap, Fluxity is providing;
    • Centralised state management
      • Huge win, any project we move into absolutely has to have some form of this.
    • Guarantees around coherent state
      • Nice to have, but was not an issue we were struggling with in the first place
    • Observable state change
      • Some good simplicity wins, this thing changed so I get notified and do my job, e.g. GraphicsSettingState
      • Some thorny edges we don’t want to have to think about.
        • We have a big mix of lifetimes, monobehaviours, statics, POCOs, shared ref in event list, etc. If we had everything in one scene and just dumped it and reloaded, we could be living the C# Unity dream, but that’s not the reality of most of our projects, we have multiple scenes that load and unload during different levels.
    • Messaging
      • Good split of sending and receiving messages in a more general way.
        • Do not want to enter into a new project without a discrete messaging system of some kind, never again suffer through a web of objects and systems direct messaging each other.
        • Some reasoning here, the direct web of function calls works but never feels like a great solution. As it becomes intolerable at one location you either make the big jump to a message system or you take the half step, making some special object/class/function that deals with that tangled mess. In practice, I think we’ve now found making that investment in a more standard messaging system from the jump to be worth it.
      • On the down side Flux isn’t ‘just’ an in-memory message passing system. There’s overhead and complexity to wrangle with if that’s all you want to do, define commands, define effects, bind them, have some state that the effect relates to. There’s more moving parts involved than a simple Sender, Receiver, Message set up we would find in a post office or something like Mediatr or an event bus.
    • What the Flux pattern aims to manage are not the big problems/timesinks we are facing right now.
      • This is definitely more Steve’s take than Actuator’s, but the things that are the biggest consumers of dev time right now are; UI, expanding the feature set of OOP style systems (in particular migrating from prototype to production circumstances and expectations), and graphics performance in a dense, outdoor, open environment.

Should others adopt Fluxity?

And now the big reveal.

Shortest version, probably not.

Slightly longer version. If you are struggling with lifetimes, direct-call spider webs, and find that you increasingly add more statics and managers as the project continues, AND you want to experience what an alternative might be, yes.

Longest version. If you don’t have the above issues, then I would only try it out of curiosity. If you do have those concerns, but don’t want to ‘experience’ an alternative, then again probably no. What I would recommend is researching your options and requirements around two core things we got out of our experiments with Flux pattern. Those two things are, centralised coherent state data, and discrete in-memory messaging.

And along that path some other projects to dig into would be;

Previous posts