В Babylon.js паттерн Observer реализован через объекты Observable и Observer, что позволяет эффективно управлять событиями и реакциями на изменения состояния. Основная идея заключается в том, что один объект (Observable) уведомляет подписчиков (Observers) о произошедших изменениях. Такой подход упрощает архитектуру приложений и обеспечивает гибкость при работе с событиями.
Объект Observable представляет собой контейнер для подписчиков. Он хранит список функций или объектов, которые должны быть уведомлены при изменении состояния.
const observable = new BABYLON.Observable();
Observable можно параметризовать типом данных, передаваемых подписчикам:
const observableVector = new BABYLON.Observable<BABYLON.Vector3>();
Это позволяет обеспечить строгую типизацию, особенно полезную при работе с TypeScript.
const observer = observable.add((data) => {
console.log("Данные обновлены:", data);
});
observable.remove(observer);
observable.notifyObservers(new BABYLON.Vector3(1, 2, 3));
Observer в Babylon.js представляет собой объект, содержащий callback-функцию и, при необходимости, уникальный идентификатор. Каждый Observer связан с конкретным Observable.
Observer создается автоматически при добавлении функции через
observable.add, но его можно сохранить для последующего
удаления:
const observer = observable.add((data) => {
console.log("Изменения:", data);
});
Удаление осуществляется через метод
observable.remove(observer). Это позволяет динамически
управлять подписчиками и освобождать ресурсы.
Observable и Observer активно используются в Babylon.js для реагирования на события камеры, материалов, света и сцены в целом.
const camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
camera.onViewMatrixChangedObservable.add((cam) => {
console.log("Камера изменила положение:", cam.position);
});
onViewMatrixChangedObservable – встроенный Observable,
который уведомляет каждый раз при изменении матрицы вида камеры.
const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter: 2}, scene);
sphere.actionManager = new BABYLON.ActionManager(scene);
sphere.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger, () => {
console.log("Сфера выбрана");
})
);
Внутри ActionManager используется собственный механизм Observable/Observer для управления событиями клика и взаимодействия.
Observable позволяет добавлять опции при регистрации Observer:
const observer = observable.add((data) => {
console.log("Только важные данные:", data);
}, null, true);
Использование масок и insertFirst особенно важно в крупных сценах, где последовательность обработки событий критична для производительности.
notifyObservers.onViewMatrixChangedObservable или
onDisposeObservable).insertFirst и маски для оптимизации
обработки событий при больших сценах.Этот подход позволяет строить масштабируемые 3D-приложения с четкой архитектурой событий, минимизируя жесткую связанность компонентов и обеспечивая эффективное управление ресурсами.