运动刚体自行移动

sce*_*nia 5 c# collision-detection rigid-bodies unity-game-engine

我的 2D Unity 游戏中有一个非常奇怪的问题,我能够将其简化为以下核心问题/最小再现测试用例。请按照以下步骤进行重现(Unity 5.1.1f1):

  • 在位置 创建一个玩家对象(立方体)(0,0,0)
  • 删除BoxCollider组件。
  • 附加以下C#脚本,Unity将自动添加所需的组件,从而使其成为刚体碰撞器。
  • 设置isKinematic标志。
  • 将另一个立方体添加到场景中的 location 处(2,0,0)
  • 删除BoxCollider组件并添加BoxCollider2D. 这使得这个立方体成为一个静态碰撞器。
  • 设置isTrigger标志。
  • 运行场景。

预期行为:
玩家立方体向另一个立方体加速,并在接触它后停止移动。

观察到的行为:
玩家立方体向另一个立方体加速,然后继续以恒定速度移动。

其他实现细节:
我最初通过平移所有对象的变换来移动它们,并且根本没有使用刚体,因为我不需要碰撞检测。现在我知道了,所以我想要刚体。我深入研究在线资源,发现我应该使用rigidbody.MovePosition()而不是transform.Translate()or transform.position。我修改了脚本,出现了上面的错误。
返回来transform.position修复问题,但这不是一个好的解决方案,因为它涉及不良实践,根据我读到的内容,会产生大量的 CPU 负载。

尝试解决失败:

  • 切换到Update()Time.deltaTime没有任何区别。
  • 我尝试不返回Update(),而是简单地将 重置timestep为设置0时。stop不用找了。
  • 摆弄检查器并执行诸如冻结刚体上的位置或将玩家对象设置为触发器之类的操作根本没有效果。在游戏运行时(碰撞后)更改 Rigidbody 组件上的任何内容都会使立方体立即停止。任何东西,甚至将其质量设置为 0。
  • 我也尝试设置velocity为0,结果没有变化。这确实有意义,因为Update()完全跳过了(Debug.Log()顺便说一句,我还用 a 检查了这一点)。

所以此时,我的代码只剩下 30 行,但我仍然不知道是什么原因造成的。由于涉及的对象是静态触发碰撞器和运动学刚体碰撞器,两者都没有物理材料,因此一旦设置了标志,就不应该有任何东西使该物体移动。但它确实会动。


SimpleController2D.cs

using UnityEngine;
using System.Collections;

[RequireComponent (typeof (BoxCollider2D), typeof (Rigidbody2D))]
public class SimpleController2D : MonoBehaviour {

    public Vector3 velocity = Vector3.zero;

    private Transform thisTransform;
    private Rigidbody2D thisRigidbody;

    public bool stop = false;

    void Awake () {
        thisTransform = GetComponent<Transform> ();
        thisRigidbody = GetComponent<Rigidbody2D> ();
    }

    void FixedUpdate() {
        float timestep = Time.fixedDeltaTime; // temporarily stored for ease of access
        if (stop) {
            return; // freeze on hit
        }

        velocity.x += timestep; // accelerate
        /* add a second slash (/) to toggle between transform and rigidbody
        thisTransform.position += velocity * timestep; /*/
        thisRigidbody.MovePosition ((Vector3)thisRigidbody.position + velocity*timestep); //*/
    }

    void OnTriggerEnter2D(Collider2D col) {
        stop = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*ann 3

解决方案

这是 Unity 5.1.1f1 中的一个错误,并在补丁版本 5.1.1p2 及更高版本中修复。

在这里获取: http://unity3d.com/unity/qa/patch-releases? version=5.1

发生了什么?

您甚至可以将问题简化为一次MovePosition调用。MovePosition使用物理引擎来移动对象。因此,Unity 会计算在下一次物理更新内到达目标位置所需的速度。版本 5.1.1f1 无法在到达位置后将速度重置为零,因此对象将继续以计算出的速度移动。