I’m new to Reactive Extensions for .NET and while playing with it I thought that it would be awesome if it could be used for games instead of the traditional update-render paradigm. Rather than trying to call Update() on all game objects, the objects themselves would just subscribe to the properties and events they are interested in and handle any changes, resulting in fewer updates, better testability and more concise queries.
But as soon as, for example, a property’s value changes, all subscribed queries will also want to update their values immediately. The dependencies may be very complex, and once everything is going to be rendered I don’t know whether all objects have finished updating themselves for the next frame. The dependencies may even be such that some objects are continuously updating based on each other’s changes. Therefore the game might be in an inconsistent state on rendering. For example a complex mesh that moves, where some parts have updated their positions and other have not yet once rendering starts. This would not have been a problem with the traditional update-render loop, as the update phase will finish completely before rendering starts.
So then my question is: is it possible to ensure that the game is in a consistent state (all objects finished their updates) just before rendering everything?
The short answer is yes, it is possible to accomplish what you’re looking for regarding game update loop decoupling. I created a proof-of-concept using Rx and XNA which used a single rendering object which was not tied in any way to the game loop. Instead, entities would fire an event off to inform subscribers they were ready for render; the payload of the event data contained all the info needed to render a frame at that time for that object.
The render request event stream is merged with a timer event stream (just an
Observable.Intervaltimer) to synchronize renders with the frame rate. It seems to work pretty well, and I’m considering testing it out on slightly larger scales. I’ve gotten it to work seemingly well both for batched rendering (many sprites at once) and with individual renders. Note that the version of Rx the code below uses is the one that ships with the WP7 ROM (Mirosoft.Phone.Reactive).Assume you have an object similar to this:
Notice that this object doesn’t describe anything how to render itself, but only acts as a publisher of data that will be used in rendering. It exposes this by subscribing Actions to observables.
Given that, we could also have an independent
RenderHandler:Note the overloaded OnRender methods which do the batching and drawing of the
Renderingevent data (it’s more of a message, but no need to get too semantic!)Hooking up the render behavior in the game class is simply two lines of code:
One last thing to do before the entity will actually render is to hook up a timer that will serve as a synchronization beacon for the game’s various entities. This is what I think of as the Rx equivalent of a lighthouse pulsing every 1/30s (for default 30Hz WP7 refresh rate).
In your game class:
Now, using the
Game‘sDrawmethod may seemingly defeat the purpose, so if you would rather avoid doing that, you could insteadPublishaConnectedObservable(Hot observable) like this:Where this technique can be incredibly useful is in Silverlight-hosted XNA games. In SL, the
Gameobject is unavailable, and a developer needs to do some finagling in order to get the traditional game loop working correctly. With Rx and this approach, there is no need to do that, promising a much less disruptive experience in porting games from pure XNA to XNA+SL