Babylon.js 场景事件执行顺序及其意义

引言

        在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 应用体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值