因为帧率不稳定,可能会导致物理引擎的迭代不一致

假设一个很简单的场景。我让一个小人恒定的向前跑的速度。比如说10m/s。使用setLinearVelocity(0,0,10)这个函数。
然后我发现在有些低端机器上。因为不能达到60帧。只能跑到30帧,这个就导致了小人跑步速度慢了一半。变成了5m/s。
通过观察物理引擎的工作原理。我发现,因为物理引擎的设置里fixedTimeStep设置的默认为0.016秒。所以如果说每秒60帧的话。每帧迭代一次,迭代时间为0.016秒,正好和实际时间是相符的。
但是如果每秒只有30帧的话,没帧只迭代一次。则实际的一秒钟在物理引擎系统里只迭代了0.5秒。就导致了,帧率越低,物理引擎越缓慢。
这个很蛋疼啊。于是我尝试如下代码

  update(deltaTime: number) {
    //不能这样子干,会抖动
    // PhysicsSystem.instance.fixedTimeStep = deltaTime;
  }

因为delatTime的不稳定,会导致物理行为直接抖动。更加蛋疼。
这个东西后续有想过怎么去搞定吗?

这个参数应该是设置固定值的,比如 fixedTimeStep = 0.016,这样可以保证每 0.016 秒更新一次物理引擎,这个方式的物理计算不受帧率影响。

我用的3.1.1,现在就是手机浏览器预览。直接表现是低端机器的帧率低的话,就跑的慢哎。你确定现在物理引擎的工作方式是和帧率无关的吗?

严格说,低帧率是出现物理计算滞后,你可以将 fixedTimeStep 设置30帧的dt间隔,即 fixedTimeStep = 0.016 * 2,然而物理帧间隔过长可能达不到表现效果。

/**
     * @en
     * The lifecycle function is automatically executed after all components `update` and `lateUpadte` are executed.
     * @zh
     * 生命周期函数,在所有组件的`update`和`lateUpadte`执行完成后自动执行。
     * @param deltaTime the time since last frame.
     */
    postUpdate (deltaTime: number) {
        if (EDITOR && !legacyCC.GAME_VIEW && !this._executeInEditMode) {
            return;
        }

        if (!this._enable) {
            this.physicsWorld.syncSceneToPhysics();
            return;
        }

        if (this._autoSimulation) {
            this._subStepCount = 0;
            this._accumulator += deltaTime;
            director.emit(Director.EVENT_BEFORE_PHYSICS);
            while (this._subStepCount < this._maxSubSteps) {
                if (this._accumulator > this._fixedTimeStep) {
                    this.physicsWorld.syncSceneToPhysics();
                    this.physicsWorld.step(this._fixedTimeStep);
                    this._accumulator -= this._fixedTimeStep;
                    this._subStepCount++;
                    this.physicsWorld.emitEvents();
                    // TODO: nesting the dirty flag reset between the syncScenetoPhysics and the simulation to reduce calling syncScenetoPhysics.
                    this.physicsWorld.syncAfterEvents();
                } else {
                    this.physicsWorld.syncSceneToPhysics();
                    break;
                }
            }
            director.emit(Director.EVENT_AFTER_PHYSICS);
        }
    }

通过观察,这个函数,我发现如果我设置迭代最大次数为1的话。那么当deltaTime传入大于0.016的时候,就会导致每帧只能迭代一次。而且只是0.016秒的迭代量,那么这个样子的话,就是会导致一直计算延迟。所以我现在改成了2。那么现在的情况就是如果delatTime过大的话。就变成了有的时候一帧可能迭代一次,有的时候可能迭代2次。这样子还是会导致抖动。emm。
所以说,物理引擎的迭代放在主loop里的话,帧率的波动就一定会导致抖动。真的很蛋疼。

确实是这样,目前没有好的解决方案,而且这种情况继续增大 fixedTimeStep 的值通常也会带来不好的物理体验 :12:

请问 ,现在3.8了 这种情况解决了吗,不同机型设置相同velocity ,impulse的情况下表现就不一致

抖动会不会是你的物理加速度设置过大导致的
image
可以试试调一下b2_velocityThreshold:https://forum.cocos.org/t/topic/124319

就简单的3D小球从空中重力落下,低端机落下速度很慢了,但是如果不用物理系统用tween则下落速度是正常的。

解决了吗哥,我现在也是这样

:sweat_smile:四年了,这个帖子还有人挖坟。我作为过来人直接告诉你结论好了,Cocos的物理系统非常不稳定,建议不要想着用这个引擎做物理游戏。

感谢哥 :sob: :sob: :sob:

感叹!之前的一个3d割草小游戏后期200+小兵加一些精英怪的时候,会帧率不稳导致游戏角色跑动速度会变化;然后就对dt<1/60时对角色的速度进行增幅,结果dt大得离谱的时候,人物直接漂移 :sweat_smile:,又对增幅倍率限制到1.5倍,才好那么一点点。