我的 2D Unity 游戏中有一个非常奇怪的问题,我能够将其简化为以下核心问题/最小的重现测试用例。请按照以下步骤重现(Unity 5.1.1f1):
- 在 location 创建一个玩家对象(Cube)
(0,0,0)
。 - 移除
BoxCollider
组件。 - 附加以下
C#
脚本,Unity 将自动添加所需的组件,从而使其成为刚体对撞机。 - 设置
isKinematic
标志。 - 在 location 处将另一个 Cube 添加到场景中
(2,0,0)
。 - 移除
BoxCollider
组件并添加一个BoxCollider2D
. 这使得这个立方体成为一个静态碰撞器。 - 设置
isTrigger
标志。 - 运行场景。
预期行为:
玩家立方体向另一个立方体加速,一旦碰到它就停止移动。
观察到
的行为:玩家立方体向另一个立方体加速,然后继续以恒定速度移动。
附加实现细节:
我最初通过平移所有对象的变换来移动所有对象,并且根本没有使用刚体,因为我不需要碰撞检测。现在我这样做了,所以我想要刚体。我深入研究了在线资源,发现我应该使用rigidbody.MovePosition()
而不是transform.Translate()
or transform.position
。我更改了脚本,出现了上述错误。
回去transform.position
解决问题,但这不是一个好的解决方案,因为它涉及不良做法,根据我的阅读,会产生大量的 CPU 负载。
尝试解决失败:
- 切换到
Update()
并Time.deltaTime
没有任何区别。 - 我尝试不返回,
Update()
而是简单地将设置重置timestep
为。不用找了。0
stop
- 摆弄 Inspector 并做一些事情,比如在刚体上冻结位置或将玩家对象也设置为触发器,这些都没有任何效果。在游戏运行时(碰撞后)更改刚体组件上的任何内容都会使立方体立即停止。从字面上看,任何东西,甚至将其质量设置为 0。
- 我也尝试设置
velocity
为0,结果没有变化。这确实是有道理的,因为Update()
它被完全跳过了(顺便说一下,我也用 aDebug.Log()
进行了检查)。
所以在这一点上,我只写了 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;
}
}