比例缩放后质心未重新计算

3
我将在运行时(实际上是在另一个物体的Start()方法中)生成一个预制对象,并需要对该对象进行缩放。我编写了一个小组件来处理这个问题:
public class Spawner : MonoBehaviour {

  public Transform SpawnPrefab;
  public Vector3 Scale;

    void Start () {
      var spawn = Instantiate(SpawnPrefab, Vector3.zero, Quaternion.identity);
      spawn.localScale = Vector3.Scale(spawn.localScale, Scale);
      // spawn.GetComponent<Rigidbody>().ResetCenterOfMass();  // Has no effect
    }
}

我正在生成的预制体的旋转中心点与物体的质心不重合。因此,重新缩放会导致相对于旋转中心点的质心位置发生变化。然而,它并没有被自动更新,因此我的生成对象具有意外的物理效果。
我尝试在调用Scale()后立即添加对GetComponent<Rigidbody>().ResetCenterOfMass()的调用(如上面的注释行),但是这没有任何效果。
然而,如果我把对ResetCenterOfMass()的调用放在一个单独的小组件的Start()方法中,例如:
public class COMReset : MonoBehaviour {
  void Start() {
    GetComponent<Rigidbody>().ResetCenterOfMass();
  }
}

这确实可以正确地重新计算质心。然而,生成的物体似乎已经通过至少一个错误的质心物理更新,因此已经获得了一些意外的动量。

为什么没有自动重新计算质心,而不需要我明确调用 ResetCenterOfMass() ?如果我必须手动触发它,那么我能否在调用 Instantiate()Scale() 后立即执行,而不是像现在这样延迟执行?


也许你需要在缩放后等待一帧来重新计算它?使用“Start协程”并在重新计算之前添加“yield return null;”(这会使它等待一帧),试试看吧 :) - Daahrien
@Lestat 谢谢 - 这确实会产生正确的COM - 但是,似乎生成的对象已经通过一个或多个带有错误COM的物理更新了,因此它已经获得了一些意外的动量...实际上,我刚意识到,我使用COMReset组件的方法也存在这个问题(尽管程度似乎较小)。 - atkins
好的,一个解决方法是将对象冻结直到重新计算(仅限一帧)。 - Daahrien
@Lestat 是的,那个方法可行 - 仍然希望找到一种不像变通方法的解决方案,但至少有一种处理这个问题的方式是很好的!感谢您提供的想法。 - atkins
@NathaliaSoragge 谢谢您的建议!我确实尝试过,但不幸的是它没有帮助。然而,我现在通过 Physics.SyncTransforms 发现了一个可靠的解决方案。 - atkins
显示剩余2条评论
1个回答

1
感谢GameDev中的@DMGregory提出的建议,调用Physics.SyncTransforms后再调用Rigidbody.ResetCenterOfMass可以解决该问题。
public class Spawner : MonoBehaviour {

  public Transform SpawnPrefab;
  public Vector3 Scale;

    void Start () {
      var spawn = Instantiate(SpawnPrefab, Vector3.zero, Quaternion.identity);
      spawn.localScale = Vector3.Scale(spawn.localScale, Scale);
      Physics.SyncTransforms();
      spawn.GetComponent<Rigidbody>().ResetCenterOfMass();
    }
}

显然,对变换比例的直接修改并没有自动传递到物理引擎,但Physics.SyncTransforms使我们能够手动将这些更改刷新到PhysX中,以便ResetCenterOfMass计算基于正确缩放的变换。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接