引言
在Babylon.js中,scene事件的执行顺序及其意义,对于开发者来说至关重要,因为它可以帮助我们更好地组织代码逻辑,优化性能,并实现复杂的交互效果。
渲染循环中的事件及其执行顺序
1. onBeforeAnimationsObservable
在动画更新之前触发。可以用于在动画执行前进行一些预处理,例如更新动画参数或调整动画状态。
2. onAfterAnimationsObservable
在动画更新之后触发。可以用于在动画执行后进行一些后续处理,如动画完成后的回调逻辑。
3. onBeforePhysicsObservable
在物理引擎更新之前触发。可以用于在物理计算之前调整物理参数或设置物理状态,以确保物理计算的准确性。
4. onAfterPhysicsObservable
在物理引擎更新之后触发。可以用于在物理计算完成后获取物理状态,例如获取物体的碰撞结果或速度变化等。
5. onBeforeRenderObservable
在场景渲染之前触发。可以用于在渲染前进行一些全局设置,如调整摄像机参数、设置渲染状态等,以确保渲染效果符合预期。
6. onBeforeRenderTargetsRenderObservable
在渲染目标渲染之前触发。可以用于在渲染目标(如纹理、阴影等)渲染前进行一些设置,以优化渲染效果和性能。
这里必须要说明一下这个onBeforeRenderTargetsRenderObservable和前面执行的onBeforeRenderObservable事件的不同。onBeforeRenderTargetsRenderObservable 在渲染目标(英文叫Render Targets是指用于存储渲染结果的缓冲区或纹理)渲染之前触发。常见的渲染目标类型通常包括一下几种:
- 阴影贴图(Shadow Map):用于存储阴影信息的纹理。通过将场景从光源的角度渲染到阴影贴图中,可以在后续的渲染中计算物体的阴影效果。
- 反射贴图(Reflection Map):用于存储反射信息的纹理。通过将场景渲染到反射贴图中,可以在后续的渲染中实现物体的反射效果。
- 环境映射(Environment Mapping):用于存储环境信息的纹理。通过将环境场景渲染到环境映射纹理中,可以在后续的渲染中实现物体的环境反射效果。
7. onAfterRenderTargetsRenderObservable
在渲染目标渲染之后触发。可以用于在渲染目标完成后进行一些后续处理,如后处理效果的应用等。
8. onBeforeCameraRenderObservable
在摄像机渲染之前触发。可以用于在摄像机渲染前进行一些设置,如调整摄像机视角、设置摄像机特效等,以实现特定的视觉效果。
这里要说一下该事件和onBeforeRenderObservable的区别。onBeforeRenderObservable是全局性的,onBeforeCameraRenderObservable是针对特定相机的,可以针对特定相机进行设置和更新,有些时候一个场景中相机有多个,所以在一帧的渲染中onBeforeCameraRenderObservable有可能会被触发多次,但是在一帧的渲染中onBeforeRenderObservable只会被触发一次。
9. onBeforeActiveMeshesEvaluationObservable
在活动网格(Active Meshes当前视图中可见的网格)评估之前触发。可以用于在评估哪些网格需要渲染之前进行一些处理,如过滤不需要渲染的网格或调整网格的渲染优先级等。
在 Babylon.js 中,每帧都会生成一个活动网格的列表,这个列表就是scene.activeMeshes, 这个scene.activeMeshes 的计算过程通常在onBeforeRenderObservable之后和 onBeforeCameraRenderObservable之前进行。
10. onAfterActiveMeshesEvaluationObservable
在活动网格评估之后触发。可以用于在评估完成后获取活动网格的信息,如网格的数量、位置等,以便进行进一步的处理。
11. onBeforeParticlesRenderingObservable
在粒子系统渲染之前触发。可以用于在粒子系统渲染前进行一些设置,如调整粒子的属性、设置粒子的渲染效果等,以实现特定的粒子效果。
12. onAfterParticlesRenderingObservable
在粒子系统渲染之后触发。可以用于在粒子系统渲染完成后进行一些后续处理,如更新粒子的状态、调整粒子的渲染参数等。
13. onBeforeDrawPhaseObservable
在绘制阶段之前触发。可以用于在绘制阶段开始前进行一些设置,如设置渲染状态、调整渲染参数等,以确保绘制过程的顺利进行。
14. onAfterDrawPhaseObservable
在绘制阶段之后触发。可以用于在绘制阶段完成后进行一些后续处理,如获取绘制结果、进行后处理效果的应用等。
15. onAfterCameraRenderObservable
在摄像机渲染之后触发。可以用于在摄像机渲染完成后进行一些处理,如更新摄像机的状态、设置摄像机的特效等,以实现特定的视觉效果。
16. onAfterRenderObservable
在场景渲染完成后触发。可以用于在渲染完成后进行一些全局处理,如更新场景状态、进行后处理效果的应用等,以确保最终渲染效果符合预期。
交互事件
场景的交互事件主要通过键盘、鼠标、触摸和游戏手柄等方式实现。以下是一些主要的交互事件及其用途:
键盘事件
onKeyboardObservable
- KEYDOWN: 当按键被按下时触发。可以用于实现键盘控制,例如移动角色或切换视角等.
- KEYUP: 当按键被释放时触发。可以用于检测按键的释放状态,例如停止某个动作或切换状态等。
以下是一个代码示例:
scene.onKeyboardObservable.add((kbInfo) => {
switch (kbInfo.type) {
case BABYLON.KeyboardEventTypes.KEYDOWN:
console.log("按键按下: ", kbInfo.event.key);
if (kbInfo.event.key === "ArrowUp") {
box.position.y += 0.1; // 向上移动立方体
}
break;
case BABYLON.KeyboardEventTypes.KEYUP:
console.log("按键释放: ", kbInfo.event.key);
break;
}
});
指针事件
onPointerObservable
- POINTERDOWN: 当指针按下时触发。可以用于检测鼠标点击或触摸开始等事件,例如开始拖动物体或触发某个交互效果等。
- POINTERUP: 当指针释放时触发。可以用于检测鼠标释放或触摸结束等事件,例如停止拖动物体或完成某个交互效果等。
- POINTERMOVE: 当指针移动时触发。可以用于实现鼠标拖动、触摸滑动等效果,例如拖动物体、滚动视图等。
- POINTERWHEEL: 当指针滚轮滚动时触发。可以用于实现缩放视图、滚动页面等效果.
- POINTERPICK: 当指针点击并选中某个物体时触发。可以用于实现点击交互,例如选中物体、触发动画等。
- POINTERTAP: 当指针轻触时触发。可以用于实现轻触交互,例如快速切换状态或触发简单效果等。
- POINTERDOUBLETAP: 当指针双击时触发。可以用于实现双击交互,例如放大视图、快速选中物体等.其他交互事件。
指针事件使用示例:
// 定义变量 isDrag
var isDrag = false;
scene.onPointerObservable.add((pointerInfo) => {
switch (pointerInfo.type) {
case BABYLON.PointerEventTypes.POINTERDOWN:
// 当鼠标按下时,将 isDrag 设置为 true
isDrag = true;
console.log("开始拖拽");
break;
case BABYLON.PointerEventTypes.POINTERUP:
// 当鼠标释放时,将 isDrag 设置为 false
isDrag = false;
console.log("结束拖拽");
break;
case BABYLON.PointerEventTypes.POINTERPICK:
// 当点击场景中的物体时,输出被选择的 mesh
if (pointerInfo.pickInfo.hit) {
var pickedMesh = pointerInfo.pickInfo.pickedMesh;
console.log("选择的物体: ", pickedMesh.name);
}
break;
}
});
ActionManager
在 Babylon.js 中, ActionManager 是一个强大的工具,用于在场景中添加和管理交互动作。它允许开发者根据不同的触发条件(如鼠标点击、键盘按键等)执行特定的动作。
- OnPickTrigger: 当用户点击或触摸某个物体时触发。可以用于实现物体的点击交互,例如改变物体的颜色、播放动画等。
- OnDoublePickTrigger: 当用户双击或双触某个物体时触发。可以用于实现双击交互,例如放大物体、快速切换状态等.
- OnPointerOverTrigger: 当指针悬停在某个物体上时触发。可以用于实现悬停效果,例如显示提示信息、高亮物体等。
- OnPointerOutTrigger: 当指针离开某个物体时触发。可以用于实现离开效果,例如隐藏提示信息、取消高亮等。
- OnKeyDownTrigger: 当某个键被按下时触发。可以用于实现键盘控制,例如移动角色、切换视角等。
- OnKeyUpTrigger: 当某个键被释放时触发。可以用于检测按键的释放状态,例如停止某个动作或切换状态等。
以下是一个代码示例:
// 为场景添加 ActionManager
scene.actionManager = new BABYLON.ActionManager(scene);
// 注册点击动作
scene.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger, function (evt) {
console.log("事件类型: ", evt.sourceEvent.type);
console.log("鼠标按钮: ", evt.sourceEvent.button);
console.log("点击坐标: (", evt.pointerX, ", ", evt.pointerY, ")");
const piciInfo = evt.pickInfo;
if (pickInfo.hit) {
console.log("拾取成功");
console.log("被拾取的网格: ", pickInfo.pickedMesh.name);
console.log("拾取点坐标: ", pickInfo.pickedPoint);
console.log("距离: ", pickInfo.distance);
console.log("面索引: ", pickInfo.faceId);
console.log("子网格索引: ", pickInfo.subMeshId);
console.log("UV 坐标: (", pickInfo.bu, ", ", pickInfo.bv, ")");
}
})
);
使用场景
- 游戏开发: 在游戏开发中,交互事件可以用于实现角色控制、物品交互、场景切换等功能。例如,通过键盘事件实现角色的移动和跳跃,通过指针事件实现物品的拾取和使用等。
- 虚拟现实: 在虚拟现实应用中,交互事件可以用于实现与虚拟环境的交互,例如通过手柄或触摸事件实现物体的抓取、放置等操作.
- 交互式展示: 在交互式展示中,交互事件可以用于实现与展示内容的互动,例如通过点击事件实现图片的放大、视频的播放等.通过合理利用 Babylon.js 的交互事件,开发者可以实现丰富多样的交互效果,提升用户的体验和应用的可玩性。
其他事件
- onReady:在场景准备好时触发。
- onDataLoaded:在数据加载完成后触发。
- onDispose:在场景被销毁时触发。
事件的意义
- 优化性能:通过合理安排事件的处理逻辑,可以避免不必要的计算和渲染,从而提高场景的渲染性能。例如,在 onBeforeRenderObservable 中进行全局设置,可以减少渲染过程中的重复计算。
- 实现复杂交互:事件的执行顺序为开发者提供了丰富的时机来实现复杂的交互逻辑。例如,在 onPointerObservable 中处理鼠标点击事件,可以实现与场景中物体的交互,如改变物体的颜色、播放动画等。
- .增强视觉效果:通过在不同的事件中应用后处理效果,可以增强场景的视觉效果。例如,在 onAfterRenderObservable 中应用模糊效果,可以实现梦幻般的视觉效果
- .灵活的代码组织:事件的执行顺序为开发者提供了灵活的代码组织方式。可以根据不同的事件类型将代码逻辑进行模块化,使代码更加清晰、易于维护和扩展。
结论
掌握 Babylon.js 场景事件的执行顺序及其意义,对于开发者来说至关重要。它不仅有助于优化性能、实现复杂的交互效果和增强视觉效果,还能使代码组织更加灵活和清晰。通过合理利用这些事件,开发者可以更好地发挥 Babylon.js 的强大功能,创造出更加丰富和沉浸式的 3D 应用体验。
326

被折叠的 条评论
为什么被折叠?



