首页 > 解决方案 > 如果刚刚更改了 transform.position,Unity,Rigidbody.MovePosition() 将不起作用

问题描述

问题

此代码有效。↓</p>

private void FixedUpdate()
{
    Vector3 newPosition = new Vector3(0, 1, 0);
    GetComponent<Rigidbody>().MovePosition(newPosition);
}

此代码不起作用。↓</p>

private void FixedUpdate()
{
    Vector3 newPosition = new Vector3(0, 1, 0);

    Vector3 oldPosition = transform.position;
    transform.position = newPosition;
    transform.position = oldPosition;

    GetComponent<Rigidbody>().MovePosition(newPosition);
}

我在 Unity 2019.4 和 2020.3 中进行了测试。

因此,如果 transform.position 刚刚更改,似乎 Rigidbody.MovePosition() 将不起作用。
为什么会这样?

2021.9.3 评论

我发现它与 Physics2D.SyncTransforms() 相关。
Physics.autoSyncTransforms , Physics.SyncTransforms

此代码有效。↓</p>

private void FixedUpdate()
{
    Vector3 newPosition = new Vector3(0, 1, 0);

    Vector3 oldPosition = transform.position;
    transform.position = newPosition;
    transform.position = oldPosition;

    Physics2D.SyncTransforms();  //newly added

    GetComponent<Rigidbody>().MovePosition(newPosition);
}

另一个小问题

另一个小问题以及我在上面编写代码的原因。

我在我的项目中没有使用太多物理。我通过设置 transform.position 改变了位置。
我学习了一些物理学,并认为 Kinematic 和 Rigidbody2D.MovePosition() 适合我。
旧代码大约有几百行。用 Rigidbody2D.MovePosition() 替换 transform.position 需要一些时间。
所以我想我可以做以下事情来节省时间:

(1)保存初始位置,
(2)使用旧代码改变位置(transform.position),
(3)保存新位置,
(4)恢复旧位置,
(5)最后使用Rigidbody2D.MovePosition(newPosition)改变位置。

但事实证明我不能在 Unity 中做到这一点。
有什么好主意吗?

标签: c#unity3dgame-physics

解决方案


首先,Rigidbody 的 MovePosition 方法只有在你不断检查碰撞/触发时才应该使用,无论附着到游戏对象的刚体是否具有连续/离散碰撞检测。如果您确实在项目中没有使用太多物理,请避免使用它并使用其变换来移动对象。

对象没有移动的原因(至少我假设这是您在屏幕上看到的)是您试图将对象的变换位置和刚体设置为相同的FixedUpdate时间戳,并且在 FixedUpdate 上更新变换很远来自任何最佳实践。如果将编辑变换位置的行移动到Update方法,它可能移动对象(取决于游戏运行的 FixedUpdate 的帧速率和时间戳)。

我的建议是,要么停止在 FixedUpdate 上更新变换的位置,只使用 rb.MovePosition 方法,要么删除 FixedUpdate 方法并在 Update() 方法上更新变换的位置。

另外,请确保您暂时不要更改 MonoBehaviour 类中其他任何地方的 transform.position、rb.position 或 rb.velocity,以确保这段代码可以正常工作。


推荐阅读