Creator3D 的 PhysicSystem 执行顺序问题

如题,假设有如下场景:

  • 有 A B 两个物体,都有Collider组件(isTrigger 为true)
  • 第01帧,A组件update方法,修改A位置,使 A B 碰撞
  • 第02帧,A组件update方法,修改A位置,使 A B 不碰撞

期望的事件执行顺序

  • 01帧 A.update
  • 01帧 A.lateUpdate
  • A B onTriggerEnter 事件触发
  • 02帧 A/B update & lateUpdate
  • A B onTriggerExit事件触发

实际的事件执行顺序

  • 01帧 A.update
  • 01帧 A.lateUpdate
  • 02帧 A/B update & lateUpdate
  • A B onTriggerEnter 事件触发
  • 03帧 A/B update & lateUpdate
  • A B onTriggerExit触发

经查看源码,问题可能位于 physic-system.ts 第 224行:

this.physicsWorld.emitEvents();  // 此处先emitEvents (使用的是上一帧的状态,没有考虑本帧update和lateUpdate可能的修改)
director.emit(Director.EVENT_BEFORE_PHYSICS);
this.physicsWorld.syncSceneToPhysics();  // emitEvents之后才执行此方法,导致物理系统更新慢了一帧

可能应该修改为:

director.emit(Director.EVENT_BEFORE_PHYSICS);
this.physicsWorld.syncSceneToPhysics(); 
this.physicsWorld.emitEvents(); 

即:先应用本帧 update 和 lateUpdate 的修改 到物理世界,再emitEvents

3赞

一种显而易见的场景:

  • 平台跳跃游戏
  • 当检测到人物与平台碰撞事件后,修改人物位置,位于平台之上
  • 由于人物和平台都是Trigger,碰撞时刻位置可能是交错的

如果按现有的执行顺序
那么必然出现一帧,人物与平台是交错的

但实际期望的是:

  • 检测到碰撞事件
  • 碰撞事件内修改了人物的位置
  • 渲染出的结果,无论如何不可能出现人物和平台的交错

目前由于,物理事件延迟了一帧生效,所以会引发这个问题

:+1:,分析很棒,当时改成延迟是因为想减少一次数据同步

另外目前物理系统,是在postUpdate,即lateUpdate后更新的。
跟文档不太一致。(但似乎是按文档所述,在update之后,lateUpdate之前更新比较合理)

好像TweenSystem,也是在lateUpdate之后才更新

的确是这样的,目前这块还在探索中。

其中物理放到后面是为了防止数据出现不同步的问题

这个问题是否有调整的计划呢? @JayceLai

或者如果通过 hack 的方式,将 PhysicSystem 的更新从 postUpdate 移到了 update,会产生什么问题吗?

之前写物理的时候也发现这个了,物理更新应该在逻辑update之前才对,unity/ue都是这样。