sce*_*nia 5 c# collision-detection rigid-bodies unity-game-engine
我的 2D Unity 游戏中有一个非常奇怪的问题,我能够将其简化为以下核心问题/最小再现测试用例。请按照以下步骤进行重现(Unity 5.1.1f1):
(0,0,0)。BoxCollider组件。C#脚本,Unity将自动添加所需的组件,从而使其成为刚体碰撞器。isKinematic标志。(2,0,0)。BoxCollider组件并添加BoxCollider2D. 这使得这个立方体成为一个静态碰撞器。isTrigger标志。预期行为:
玩家立方体向另一个立方体加速,并在接触它后停止移动。
观察到的行为:
玩家立方体向另一个立方体加速,然后继续以恒定速度移动。
其他实现细节:
我最初通过平移所有对象的变换来移动它们,并且根本没有使用刚体,因为我不需要碰撞检测。现在我知道了,所以我想要刚体。我深入研究在线资源,发现我应该使用rigidbody.MovePosition()而不是transform.Translate()or transform.position。我修改了脚本,出现了上面的错误。
返回来transform.position修复问题,但这不是一个好的解决方案,因为它涉及不良实践,根据我读到的内容,会产生大量的 CPU 负载。
尝试解决失败:
Update()和Time.deltaTime没有任何区别。Update(),而是简单地将 重置timestep为设置0时。stop不用找了。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)
这是 Unity 5.1.1f1 中的一个错误,并在补丁版本 5.1.1p2 及更高版本中修复。
在这里获取: http://unity3d.com/unity/qa/patch-releases? version=5.1
您甚至可以将问题简化为一次MovePosition调用。MovePosition使用物理引擎来移动对象。因此,Unity 会计算在下一次物理更新内到达目标位置所需的速度。版本 5.1.1f1 无法在到达位置后将速度重置为零,因此对象将继续以计算出的速度移动。