How To

Handle Events with Observables


How To Use Observables

Introduction

Babylon.js provides a lot of events (like scene.beforeRender) and before v2.4 there was not a unified way to handle them. Starting with v2.4, we introduced (without breaking backward compatibility of course) a new pattern: the Obervables.

There are two parts: the Observable and the Observer. The Observable is a property of an object which represents a given event (like beforeRender for instance). Users that want to have their own piece of code running in response to such event will register an Observer to the appropriate Observable. Then it's the duty of the Observable to execute the Observers, when appropriate.

Observable

The implementer uses it to create a property which will trigger all the registered observers. The Generic type T is used to communicate a given data type from the Observable to the Observer.

You have the following method/properties:

  • add(): to add an Observer
  • remove(): to remove a previously registered Observer
  • removeCallback(): same as above but giving the callback instead of the Observer instance
  • notifyObservers(): used to notify all the registered Observers (with a little special feature I'll detail further below)
  • hasObserver: a property that returns true if at least one Observer is registered
  • hasSpecificMask(mask): a function that returns true if at least one Observer is registered with this mask
  • clear() to remove all Observers
  • clone() to simply clone the object but not the registered Observers.

Observer

An Observer is created when you call the Observable.add() method. When you no longer want to be notified, you call Observable.remove() giving the same object.

Example!

Given code to be run on every frame before the scene starts the rendering:

var alpha = 0;
scene.onBeforeRenderObservable.add(function () {
    sphere.scaling.y = Math.cos(alpha);

    alpha += 0.01;
});

When you want to later remove your observer, you just need to store in var during creation, then use it to remove:

var alpha = 0;
var observer = scene.onBeforeRenderObservable.add(function () {
    sphere.scaling.y = Math.cos(alpha);

    alpha += 0.01;
});

scene.onBeforeRenderObservable.remove(observer);

Scene Object Observables

The BabylonJS Scene Object has over 20 observables that 'fire' under various conditions. Most of them are checked EACH frame/render, and in a deterministic/predictable order or sequence. Below is a list of Scene observables checked during each renderLoop... in the order they are checked:

  • onBeforeAnimationsObservable
  • onAfterAnimationsObservable
  • onBeforePhysicsObservable
  • onAfterPhysicsObservable
  • onBeforeRenderObservable
  • onBeforeRenderTargetsRenderObservable
  • onAfterRenderTargetsRenderObservable
  • onBeforeCameraRenderObservable
  • onBeforeActiveMeshesEvaluationObservable
  • onAfterActiveMeshesEvaluationObservable
  • onBeforeParticlesRenderingObservable
  • onAfterParticlesRenderingObservable
  • onBeforeRenderTargetsRenderObservable
  • onAfterRenderTargetsRenderObservable
  • onBeforeDrawPhaseObservable
  • onAfterDrawPhaseObservable
  • onAfterCameraRenderObservable
  • onAfterRenderObservable

The Scene Object also has observers: onReady, onDataLoaded, onDispose, but they do not happen within a rendering/frame.

Also, onBeforeStep and onAfterStep are available when using deterministic lock step