About RMC & Unity3D Rivello Multimedia Consulting (RMC) provides consulting services for applications and games. RMC specializes in Unity3D development (see our work here). Please contact us today with any questions, comments, and project quotes. As always, RivelloMultimediaConsulting.com/unity/ will be the central location for deep articles and tutorials, Facebook.com/RivelloMultimediaConsulting (like us!) will engage the growing RMC+Unity community, and for the latest opinions and cool links follow me at Twitter.com/srivello.
You can read more in my first article “Unity3D Reactive Extensions 1: An Introduction“. That is recommended reading before continuing with the article below.
How to do RX?
Here is a recap. In article 1 we used an RX approach for the following (academic) exercise;
Exercise: Dispatch a double click event based on custom timing parameters.
Reactive Extensions (RX) Solution
You can see the code is easy to read and powerful. While this algorithm requires state management, we don’t have to handle it directly. The internals of RX do it for us. You can imagine with a more complex feature, the code would be dramatically more than the RX solution. Below we break-down the code and explain each step.
NOTE: The TLP Library used in this article is a work in progress. It features only limited functionality and does not conform to common RX standards in the naming, signature, and structure of major elements. These differences are why the syntax and marble diagram names below are not 100% coincidental, but the concepts are similar. The TLP team invites other developers to fork the library and contribute to it. Still it is a fantastic learning tool and quite useful as-is.
Complete Code For RX Solution
/// Use this for initialization
void Start ()
float maxTimeAllowedBetweenSingleCLicks_float = 1;
float delayBetweenAllowingADoubleClick_float = 5;
int clicksRequiredForADoubleClick_int = 2;
// CREATE OBSERVABLE
//(ORDER IS NOT IMPORTANT, BUT SUBSCRIBE MUST BE LAST)
var mouseDoubleClickObservable = Observable
//RUN IT EVERY FRAME (INTERNALLY THAT MEANS Update()
//FILTER RESULTS OF THE FRAME
//WE CARE ONLY ‘DID USER CLICK MOUSE BUTTON?’
//DID WE FIND X RESULTS WITHIN Y SECONDS?
.withinTimeframe (clicksRequiredForADoubleClick_int, maxTimeAllowedBetweenSingleCLicks_float)
//REQUIRE SOME ‘COOL-DOWN-TIME’ BETWEEN SUCCESSES
//FOR EVERY EVENT THAT MEETS THOSE CRITERIA, CALL A METHOD
var subscription = mouseDoubleClickObservable
Debug.Log ("Subscription Setup : " + subscription);
/// SUCCESS: Double click
private void _onMouseEvent (MouseEventType aMouseEventType)
Debug.Log ("RX._onMouseDoubleClick() " + aMouseEventType);
Marble Diagrams & RX Syntax
Marble diagrams are frequently in videos and blog entries from the Rx team explaining how certain operators in Rx work. From top to bottom there are; source stream(s), operators, and then the outgoing stream. The RXJava wiki has an especially pretty set of these images.
Let’s take a closer look at the syntax we used.
- 1. everyFrame: We observe an event stream on every frame (aka Update) in Unity…
- 2. filter: …where the mouse button is down…
- 3. withinTimeFrame: … X occurrences within Y seconds, which we call success…
- 4. onceEvery: …and success can only happen every Z seconds…
- 5. subscribe: …then call the desired method…
1. Operator: everyFrame (Similar to fromEvent)
2. Operator: filter
You can filter an Observable, discarding any items that do not meet some test, by passing a filtering function into the
filter( ) method. For example, the following code filters a list of integers, emitting only those that are even (that is, where the remainder from dividing the number by two is zero):
3. Operator: withinTimeFrame (Similar to buffer)
buffer( ) method periodically gathers items emitted by a source
Observable into bundles, and emits these bundles as its own emissions. There are a number of ways with which you can regulate how
buffer( ) gathers items from the source
Observable into bundles:
4. Operator: onceEvery (Similar to sample)
5. Operator: subscribe
Subscribe is not an operator per se, it is something higher level in importance — When an observer subscribes to an observable sequence, the sequence begins and runs till completion. It is in the subscribe that we answer “What should ultimately happen with the outgoing event stream?”. In our example, we call a local method _onMouseEvent and we pass an appropriate MouseEventType.
Our exploration into RX has just begun. Everyone interested is invited to download the source-code from my first article “Unity3D Reactive Extensions 1: An Introduction” and learn more. I continue to seek to find the best RX library for Unity development and have already begun to add RX into my game projects.`