Reactive Programming: An Introduction for Game Developers

Hey guys,

just wanted to share this article I’ve written with you: https://medium.com/@u.hanselmann/reactive-programming-an-introduction-for-game-developers-f7da00edb424

Let me know what you think.

Cheers,
Chris

1 Like

Wait what?

I’m a pretty competent programmer. But reading the article left me with absolutely no clue what reactive programming is. Or when and why I should use it.

Perhaps take a few sentences to give a high level description of the concept before diving into details?

1 Like

Okay back. Out of curiosity I went to Wikipedia to figure out what reactive programming is. Turns out the ladder logic, relay control, and pneumatics that I use in my day job are perfect examples of reactive programming.

I still don’t think it’s a hugely useful paradigm for game development in Unity. The idea of wrapping UI elements in a seperate stream class that contains its own ability to update the UI is a good one, but I’m not convinced it’s worth the extra complexity for many projects. Or that it’s better then the alternatives.

3 Likes

Yea, it reads like a dan brown novel. Ham-handed building of suspense is fine in an action novel, not so much in a tech introduction/article. I had to read pretty far to get any idea of where it was going. And that was after several examples. Also, the examples are a little misleading, as compare it to suboptimal ways of doing it in the first place. Yes, it improves on updating the UI from the player script, but that’s a suboptimal way in the first place.

Yea, it is interesting, but don’t really see a use case that it solves for the amount of complexity it adds. Delegates, properly used would largely solve the most common issues it attempts to address. But interesting nonetheless.

2 Likes

I haven’t read the article (I’m pretty familiar with the reactive model) but I have to disagree… it takes awhile to “get it” but once it clicks, it’s one of those things where other approaches suddenly look very wrong and unnecessarily complicated.

Actually it reminds me of when I finally understood true resource-representation-driven HTTP representational state transfers – I had to forget the badly-broken model that is how the web uses HTTP today and just kind of absorb Dr. Fielding’s literal explanations of how it’s supposed to work – and now practically everything about web development just looks sadly broken and stupid.

I’d do all sorts of unnatural and regrettable things for real F# support in Unity. :smile:

Reactive programming is a different way of thinking about the interaction between objects. It’s a paradigm shift for logic flow akin to how component-driven architecture is. We know that composite objects are better than deep inheritance trees for games, largely because component logic can be made smaller and more easily reusable across multiple different game entities. The reusable code not only reduces bugs, but it invites more expressive design as each component does what it says, and little else. Rx is similar in its desire to reduce complex methods to simpler reactions. What Rx brings to the table is a clean way to compose events.

I applaud the author’s desire to increase visibility of Rx. However, I feel that this article failed to put forth the strengths of the paradigm for people who don’t already have some understanding of it. People may have a better opinion of the article after reading http://sugarpillstudios.com/wp/?page_id=279.

Scripts are often written in such a way that they wake up, check the state of the game, then perform some operation based on that state. Solid event-driven scripts will wake up, subscribe to some event, and then upon hearing that event will check the state of the game and perform some operation based on that state. What is really going on here is that these scripts are trying to determine when to perform an operation. A lot of code is being written to help determine when.

Much like component-driven design, it isn’t the end-all-be-all of programming. I do encourage people to spend the time needed to grok it. It is another tool to have in one’s toolbag.

1 Like

That actually does give me a far better understanding of the concept, and how it might apply to games.

I’m still not sold on actually learning and using it. But I can appreciate where it might be useful.

1 Like

The fact that he hijacked the “Everything is a Stream” picture from this other article reminded me that the article linked below is a very good, very clear introduction to RP.

So the term “Reactive programming” comes from an official microsoft C# add-on? Seems like the more traditional term would be customizable events.

I think the more common Unity solution is coroutines. Both (setting up an event, starting a “check for this” coroutine) are a fire&forget way to take it out of the main loop.

I agree with @zombiegorilla , I’m not seeing a strong benefit to condensing a bunch of logic into Linq queries.

Like what really is the difference between this example:

IObservable<float> whenToSteer = keyPresses
  .Where( key => key == Keys.Left || key == Keys.Right )
  .Select( key => key == Keys.Left ? -0.05f : +0.05f );
whenToSteer.Subscribe( steer );

and this:

public UnityEvent<float> whenToSteer;

void Awake() {
    whenToSteer = new UnityEvent<float>();
    whenToSteer.AddListener(Steer);
}

void Update() {
    if(Input.GetKey(KeyCode.LeftArrow)) {
        whenToSteer.Invoke(-0.05f);
    } else if(Input.GetKey(KeyCode.RightArrow)) {
        whenToSteer.Invoke(0.05f);
    }
}

void Steer(float amount) {}

What is the benefit that warrants the total change in design? It seems like the more complex the event logic gets, the less readable the queries get and the harder it becomes to debug.

Am I missing something?

4 Likes

Also new to the concept, but reading this introduction, it sounds an awful lot like how I use UnityEvents. I use them not just for UI, but for all sorts of communication between components and objects, any time something event-like happens (including things like a change in a character’s hit points). I snap these together into what you could call “streams,” sometimes including going through little components I call “relays” (but which the Reactive folks would call filters).

For example, I have a relay with a public method that takes a Boolean parameter, which then invokes one of two UnityEvents depending on whether that is true or false. I have a similar relay that works with numeric values, and invokes appropriate events for when the parameter given is >, ==, or < some threshold; others that pass the event along after a delay, etc.

And so I put these together into chains as needed to get the meat of my code the data and notifications it needs whenever anything happens. Am I doing reactive programming without even knowing it?

1 Like

Probably. What you describe is certainly a core part of reactive thinking. A key concept is thinking of the execution of your program in terms of the flow of data and events. I think all of us imperative programmers come around to the concept of events and logic flow at some point. Even though we still like to describe our operations imperatively, we start to think in terms of reactivity. Rx, in part, is a set of operators that help reduce the inertia of the creation of new events. Observables can be thought of as events that are easy to compose. That you end up writing some similar operators on your own is pretty cool.

I should note that I think that Rx is a useful thing to learn, but I think that Unity’s implementation of it still needs some maturation. For example, UniRx doesn’t have the Window or Join operators yet. These are some powerful operators that I sorely miss.

1 Like

No, it’s much older than that, MS just built one of the more-popular implementations in common use.