What Is Reactive Programming In Unity, UniRX
There are various paradigms we use in programming. These represent the fundamental approach, way of thinking, or programming model we follow when writing a program. In other words, they are the general framework of methods and structures used to solve a problem. It’s the philosophy that inspires us while coding. Reactive programming is one of them.
So, what is the philosophy of reactive programming?
“When something changes, something else should automatically happen.”
Reactive programming is about specifying how the code should respond when a certain condition occurs. In essence, we define how it should react -just like the name suggests!
Reactive programming is based on four core principles. By understanding these principles, we can learn how to write reactive code and design a reactive system architecture.
- Responsive — the system responds quickly and consistently
- Resilient — it continues to function even in the face of failures
- Elastic — it adjusts itself as the load increases; it is scalable
- Message Driven — components communicate through messages
You can visit the link below to explore the Reactive Manifesto.
Why Should I Embrace Reactive Programming?
Reactive programming raises the level of abstraction in architecture. This allows you to focus more on the dependencies between events within the business logic. It makes the code cleaner and more readable.
Reactive programming helps us handle asynchronous situations and uncertainties. It adapts to these uncertain conditions and reacts to changes in a reactive way. The time window in which such changes are expected is called a stream. We expect everything to happen within this time frame.
Real-Life Examples
For example, let’s think of a Conveyor Belt Sushi setup. There are plates of sushi on the belt. The time window in which we wait for the plate we want is our stream. Everything can be a stream. We can create these streams however we like.
In this case, the stream is the duration the conveyor belt is running. When the restaurant opens in the morning, the stream actually starts, and it continues until it is stopped.
Customers in the restaurant constantly watch the conveyor belt until the plate they are waiting for arrives. In this context, the plates are like events that trigger us into action.
In this scenario, the observing customer is, of course, our observer.
This should sound familiar — it closely resembles the Observer Pattern, right? Exactly. Reactive Programming adopts this approach, but with some additions. Let’s think about those extras.
In Reactive Programming, we treat streams as immutable. This allows us to take each stream, apply specific operations to it, and use chained operations to listen to the events in the stream according to our needs.
So instead of the imperative “if this happens, do that” logic from the observer pattern, we apply functional transformations over the data flow.
Streams streams…🚣♀️
For example, imagine a river filled with fish. In the initial stream, there are various fish swimming at different frequencies within the stream.
Later on, if we want to create a new stream that contains only the red fish, we can do that using the existing stream.
Here, the filtering operation we applied on the first stream did not modify the original stream. Instead, it created a new stream that contains only the red fish.
So, what if we now want to create a new stream based on the frequency of the fish?
In this way, we grouped the fish that appeared less than one second apart. Once again, a new stream was created.
Now, by mapping this stream, we want to create another stream based on the count of fish in each group.
Stream 4 is the mapped version of Stream 3, based on the fish counts in each group.
Get Gulnaz Gurbuz’s stories in your inbox
Join Medium for free to get updates from this writer.
Now, I’m only interested in groups that contain 2 or more fish.
In this case, if I filter the stream again, I’ll end up with a new stream that includes only the groups meeting this condition.
In this way, I reach Stream V.
This stream now provides me with an event that gets triggered whenever 2 or more red fish pass through from the original stream.
Once this condition is met and the event is triggered, I can perform any action I want.
UniRX
We will now take a look at UniRX, a reactive programming library developed specifically for Unity.
The main purpose of UniRX is to make asynchronous operations and event-driven systems easier to manage.
Let’s go through a simple example:
var clickStream = Observable.EveryUpdate()
.Where(_ => Input.GetMouseButtonDown(0))
.Subscribe(_ => Debug.Log("Mouse Clicked"));This code listens for mouse clicks on every frame using UniRX.
Observable.EveryUpdate()creates a stream that emits a value every frame..Where(...)filters the stream, only passing through frames where the left mouse button was clicked..Subscribe(...)reacts to those filtered events, in this case by logging "Mouse Clicked" to the console.
clickStream.Buffer(clickStream.Throttle(TimeSpan.FromMilliseconds(250)))
.Where(xs => xs.Count >= 2)
.Subscribe(xs => Debug.Log("DoubleClick Detected! Count:" + xs.Count));clickStream: The stream that emits events on every click.Throttle(...): Emits a signal only if no new event occurs within 250 milliseconds. It's used to detect a pause in the click activity.Buffer(...): Groups all click events until a signal is received fromThrottle. So, clicks that happen within short intervals (less than 250ms between them) are collected together into a list.Where(...): Filters those groups based on the number of clicks they contain.Subscribe(...): If the group has 2 or more clicks, this method is invoked, and a log is printed.
This code detects rapid consecutive clicks by buffering them together based on timing. When 2 or more clicks happen within 250 milliseconds, it logs that a double-click (or more) has been detected.
In What Situations Can We Use UniRX?
- UI Interactions
- Input Management
- Network Events
- Animation and Timed Operations
- State Management
What Can We Make Observable?
- Unity Lifecycle Events (e.g., Update, FixedUpdate)
- Triggers and Collision Events
- UI Events
- Through ReactiveProperty and Reactive Collections, we can observe data like a stream
- Custom Events
- Coroutines









