当前位置: 首页 > article >正文

说说Babylon.js中scene.deltaTime的大坑

诡异的问题      

        下面是给一个材质设置发光颜色周期变化和纹理偏移的代码,你能感觉到这里面可能出现的问题吗?

        var passTime = 0;
        var uOffset = 0;
        var deltaTime = 0;

        function SetEmissiveColor() {
            passTime += scene.deltaTime * 0.05;
            if(passTime > 6.2832) passTime -= 6.2832;
            var multi = (Math.sin(passTime) + 1) * 0.5;
            material.emissiveColor = new BABYLON.Color3(9 * multi, 2.75 * multi, 0);

            var offset = scene.deltaTime * 0.001;
            material.diffuseTexture.uOffset -= offset;
            material.opacityTexture.uOffset -= offset;
        }

        scene.onBeforeRenderObservable.add(SetEmissiveColor);

        实际在浏览器中运行时,你会发现有可能完全没有实现预期的效果。如果你打印一下passTime的值,可能是一直都是NaN,所以最终会导致material.emissiveColor 的值完全不可用。

        这是咋回事呢?原来scene.deltaTime  在场景的第一帧渲染之前是  undefined,这导致 passTime变量在下面这行代码

passTime += scene.deltaTime * 0.05;

执行的时候就变成了NaN,然后NaN的自增就一直是NaN了,所以计算得到的颜色值也就一直错了,哈哈。

       下面说说解决方法。

解决方法一

        添加if语句检查scene.deltaTime的值是否可用,参考代码如下:

        var passTime = 0;
        var uOffset = 0;
        var deltaTime = 0;

        function SetEmissiveColor() {
            if (scene.deltaTime !== void 0 && !isNaN(scene.deltaTime)){

                passTime += scene.deltaTime * 0.05;
                if(passTime > 6.2832) passTime -= 6.2832;
                var multi = (Math.sin(passTime) + 1) * 0.5;
                material.emissiveColor = new BABYLON.Color3(9 * multi, 2.75 * multi, 0);

                var offset = scene.deltaTime * 0.001;
                material.diffuseTexture.uOffset -= offset;
                material.opacityTexture.uOffset -= offset;
            }
        }

        scene.onBeforeRenderObservable.add(SetEmissiveColor);

        上述代码在执行passTime的自增的之前通过 if 语句对scene.deltaTime进行了检查,这样就不会在scene.deltaTime不可用的时候进行计算了。

        知识点:scene.deltaTime !== void 0 这个判断里面也可以写成 scene.deltaTime !== undefined,但是这里为啥用的是 void 0 而没有用undefined 呢,下面这个链接讲了这个问题:

 关于void 0 与 undefined。

解决方法二

        使用定时器,由于scene.deltaTime只是在第一帧渲染完成之前有问题,就没有必要每帧判断,下面的代码在定时器中判断scene.deltaTime的值,待其合理之后再把SetEmissiveColor方法添加到scene.onBeforeRenderObservable事件中,与此同时移除了这个定时器,这样就避免了每帧都要检查scene.deltaTime的合理性。参考代码如下:

        var passTime = 0;
        var uOffset = 0;
        var deltaTime = 0;

        function SetEmissiveColor() {

                passTime += scene.deltaTime * 0.05;
                if(passTime > 6.2832) passTime -= 6.2832;
                var multi = (Math.sin(passTime) + 1) * 0.5;
                material.emissiveColor = new BABYLON.Color3(9 * multi, 2.75 * multi, 0);

                var offset = scene.deltaTime * 0.001;
                material.diffuseTexture.uOffset -= offset;
                material.opacityTexture.uOffset -= offset;
        }

        var checkDeltaTime = setInterval(function () {
            if (scene.deltaTime !== void 0 && !isNaN(scene.deltaTime)) {

                scene.onBeforeRenderObservable.add(SetEmissiveColor);//scene.deltaTime可用之后再添加到事件中

                clearInterval(checkDeltaTime); // 清除定时器
            }
        }, 20); // 每20毫秒检查一次

解决方法三

        不使用scene.deltaTime,改用engine.getDeltaTime()方法,参考代码如下:

        var passTime = 0;
        var uOffset = 0;
        var deltaTime = 0;

        function SetEmissiveColor() {

           passTime += engine.getDeltaTime() * 0.05;
           console.log(engine.getDeltaTime());
           if(passTime > 6.2832) passTime -= 6.2832;
           var multi = (Math.sin(passTime) + 1) * 0.5;
           material.emissiveColor = new BABYLON.Color3(9 * multi, 2.75 * multi, 0);

           var offset = engine.getDeltaTime() * 0.001;
           material.diffuseTexture.uOffset -= offset;
           material.opacityTexture.uOffset -= offset;
        }

        scene.onBeforeRenderObservable.add(SetEmissiveColor);

        这里的engine.getDeltaTime()在第一帧渲染完成之前会被赋值为0,不会出现值为NaN的情况(scene.deltaTime为啥就不能这么干呢???)。

        好了,就到这里,通过这个问题又学会了一些东西,大家共勉。


http://www.kler.cn/a/506679.html

相关文章:

  • 微软开源AI Agent AutoGen 详解
  • 传统摄像头普通形态的系统连接方式
  • ros2笔记-6.2 使用urdf创建机器人模型
  • ecmascript:2.模版字符串
  • 【Linux】11.Linux基础开发工具使用(4)
  • 《leetcode-runner》如何手搓一个debug调试器——指令系统
  • 如何异地远程访问本地部署的Web-Check实现团队远程检测与维护本地站点
  • 《DeepSeek V3:重新定义AI大模型的效率与成本》
  • Qt实现防止程序多次运行
  • Java学习教程,从入门到精通,JDBC数据库连接语法知识点及案例代码(92)
  • Outlook 无网络连接[2604] 错误解决办法
  • python批量doc转pdf调用提示库未注册
  • 华北水利水电大学第十届ACM/ICPC程序设计新生赛题解
  • Django Admin 实战:实现 ECS 集群批量同步功能
  • 【6】Word:海名公司文秘❗
  • SuperMap iClient3D for Cesium立体地图选中+下钻特效
  • 【Docker】使用Dev Container进行开发
  • HTML 中的 Window 和 Document 介绍
  • 【Uniapp-Vue3】manifest.json配置
  • 前后端分离开发心得
  • 十分钟带汝入门大数据开发语言Scala
  • 序列化和反序列化 Json 字符串 @JSONField
  • XML在线格式化 - 加菲工具
  • Flurl:一个Star 3.9K的链式RESTful风格HTTP开源.Net库
  • 【Linux】13.Linux进程概念(2)
  • OSPF的LSA的学习研究