我在运行时生成一个预制对象(实际上,在另一个对象的 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
}
}
我生成的预制件的枢轴点与对象的质心不重合。因此,重新缩放意味着相对于枢轴的质心位置将发生变化。但是,它不会自动更新,因此我生成的对象具有意外的物理特性。
我尝试添加对 GetComponent<Rigidbody>().ResetCenterOfMass()
的调用在调用 Scale()
后立即(上面注释掉的行),但这没有任何效果。
但是,如果我把电话拨给 ResetCenterOfMass()
在Start()
添加到生成对象的单独小组件的方法,例如
public class COMReset : MonoBehaviour {
void Start() {
GetComponent<Rigidbody>().ResetCenterOfMass();
}
}
这确实导致重心重新计算正确。然而,此时生成的对象似乎已经通过错误的 COM 进行了至少一次物理更新,因此已经获得了一些意想不到的动力。
为什么 COM 没有被自动重新计算,而我不必调用 ResetCenterOfMass()
明确地?如果我必须手动触发它,我可以在调用 Instantiate()
后立即执行吗?和 Scale()
,而不是像这样推迟?
最佳答案
感谢@DMGregory GameDev如需建议,请调用 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
计算随后基于正确缩放的变换。
关于c# - 缩放后未重新计算质心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51377676/