129 lines
5.6 KiB
Markdown
129 lines
5.6 KiB
Markdown
# Туториал: отладка Babylon-сцены
|
||
|
||
Полезные приёмы когда «что-то не рендерится» или «тормозит».
|
||
|
||
## 1. Inspector (визуальный debug)
|
||
|
||
В Console браузера:
|
||
```js
|
||
window.__scene.debugLayer.show({ embedMode: true });
|
||
```
|
||
|
||
Откроется панель Babylon Inspector справа:
|
||
- **Scene** — список всех мешей, лампочек, материалов
|
||
- **Stats** — FPS, число draw calls, мегабайты в VRAM
|
||
- **Performance** — graph загрузки CPU/GPU
|
||
|
||
Чтобы скрыть: `__scene.debugLayer.hide()`.
|
||
|
||
## 2. Подсветить меш
|
||
|
||
В Inspector кликни по мешу — он подсветится зелёным wireframe-ом на сцене. Видно где он, какого размера, не «улетел ли в космос».
|
||
|
||
В коде:
|
||
```js
|
||
const mesh = scene.getMeshByName('Cube1');
|
||
mesh.showBoundingBox = true; // покажет AABB
|
||
mesh.material.wireframe = true; // рендер каркасом
|
||
```
|
||
|
||
## 3. Логи FPS / draw calls
|
||
|
||
```js
|
||
scene.onAfterRenderObservable.add(() => {
|
||
if (scene.getEngine().performanceMonitor.averageFPS < 30) {
|
||
console.warn('FPS dropped:', {
|
||
fps: scene.getEngine().performanceMonitor.averageFPS,
|
||
drawCalls: scene.getEngine().drawCalls,
|
||
activeMeshes: scene.getActiveMeshes().length,
|
||
});
|
||
}
|
||
});
|
||
```
|
||
|
||
## 4. Профайлинг кадра
|
||
|
||
В Chrome DevTools → Performance → Record (10 сек игры). Смотри:
|
||
- **Scripting** > 10мс — твой JS тормозит. Гляни Bottom-Up — самые тяжёлые функции.
|
||
- **Rendering** > 5мс — GPU не справляется. Уменьши число мешей или текстур.
|
||
- **Painting** — обычно мало в WebGL.
|
||
|
||
## 5. Babylon Spector.js
|
||
|
||
Глубокая отладка одного кадра WebGL. Установи расширение [Spector.js](https://spector.babylonjs.com/). Кнопка «Capture frame» → видишь каждый draw call, каждую текстуру, каждый shader.
|
||
|
||
Полезно когда:
|
||
- Странные артефакты (одна модель «мерцает»)
|
||
- Текстура не накладывается (видишь pink/purple)
|
||
- Не понятно почему столько draw calls
|
||
|
||
## 6. Прозрачные / невидимые меши
|
||
|
||
Часто меш «есть, но не видно». Чек-лист:
|
||
```js
|
||
const m = scene.getMeshByName('Foo');
|
||
console.log({
|
||
isEnabled: m.isEnabled(),
|
||
isVisible: m.isVisible,
|
||
visibility: m.visibility, // 0 = прозрачный, 1 = непрозрачный
|
||
position: m.position,
|
||
scaling: m.scaling, // не 0?
|
||
material: !!m.material,
|
||
hasTexture: !!(m.material && m.material.diffuseTexture),
|
||
textureLoaded: m.material?.diffuseTexture?.isReady(),
|
||
});
|
||
```
|
||
|
||
## 7. Утечки памяти
|
||
|
||
Каждый `scene.createMesh` без последующего `mesh.dispose()` — утечка. Проверь через Inspector → Statistics → Allocated GPU memory растёт со временем = течь.
|
||
|
||
Типичные источники:
|
||
- GLB загружен через `SceneLoader.ImportMesh` без `AssetContainer` — материалы и текстуры не освобождаются.
|
||
- `setInterval` создающий новые меши и не убирающий старые.
|
||
- Listener'ы `onClick/onPointer` накапливаются, держат refs.
|
||
|
||
## 8. Console команды для быстрой отладки
|
||
|
||
```js
|
||
// Сколько мешей сейчас на сцене
|
||
__scene.meshes.length
|
||
|
||
// Топ-10 по числу вершин
|
||
__scene.meshes.slice().sort((a,b)=> b.getTotalVertices() - a.getTotalVertices()).slice(0,10).map(m=>[m.name, m.getTotalVertices()])
|
||
|
||
// Удалить все debug-marker'ы
|
||
__scene.meshes.filter(m=>m.name.startsWith('__debug_')).forEach(m=>m.dispose())
|
||
|
||
// Заморозить материалы (не пересчитывать uniforms каждый кадр)
|
||
__scene.materials.forEach(m=>m.freeze())
|
||
// ! не делать если материалы меняются в runtime — иначе зависнут на текущем значении
|
||
|
||
// FPS-overlay на сцене
|
||
new BABYLON.FreeCamera('debug', new BABYLON.Vector3(0,5,-10), __scene);
|
||
```
|
||
|
||
## 9. Что не делать (часто ломает FPS)
|
||
|
||
- `scene.render()` руками — Babylon сам в RAF
|
||
- `blockMaterialDirtyMechanism = true` — лагает новые меши (debris, эффекты)
|
||
- `createOrUpdateSelectionOctree()` каждый кадр — пересчёт O(N²)
|
||
- `mesh.getBoundingInfo()` в hot path — есть кеш `mesh._boundingInfo`
|
||
- `setInterval(... , 16)` — используй `scene.registerBeforeRender(fn)` (тогда привязано к рендер-циклу Babylon)
|
||
|
||
## 10. Мобильная отладка
|
||
|
||
Открой Chrome на десктопе → DevTools → ⋮ → More tools → Remote devices. Подключи Android через USB, открой плеер на нём — твой DevTools покажет console/network/dom мобильной вкладки.
|
||
|
||
iOS аналогично через Safari → Develop → <device>.
|
||
|
||
## Что почитать
|
||
|
||
- https://doc.babylonjs.com/features/featuresDeepDive/inspector
|
||
- https://spector.babylonjs.com/
|
||
- [reference_kubikon_scripting_api.md](../../disaster-recovery/...) — приватный референс API для скриптов
|
||
|
||
## Вопросы
|
||
|
||
В канал `#разработка` на https://team.rublox.pro.
|