我在我的2D Unity游戏中遇到了一个非常奇怪的问题,我能将其简化为以下核心问题/最小重现测试用例。按照以下步骤复现(Unity 5.1.1f1):
创建一个位于位置(0,0,0)的玩家对象(Cube)。
删除BoxCollider组件。
附加以下C#脚本,Unity会自动添加所需的组件并使其成为刚体碰撞器。
设置isKinematic标志。
在场景中添加另一个Cube,位置为(2,0,0)。
删除BoxCollider组件并添加BoxCollider2D。这将使此立方体成为静态碰撞器。
设置isTrigger标志。
运行场景。
预期行为: 玩家方块加速向其他方块移动,并在触碰到其他方块时停止移动。
观察到的行为: 玩家方块加速向其他方块移动,然后以恒定速度继续移动。
附加实现细节: 我最初通过转换它们的变换来移动所有对象,并且根本没有使用Rigidbodies,因为我不需要碰撞检测。现在我需要,所以我想要Rigidbodies。我深入研究了在线资源,并发现我应该使用rigidbody.MovePosition()而不是transform.Translate()或transform.position。我更改了我的脚本,上述错误出现了。 回到transform.position可以解决问题,但这不是一个好的解决方案,因为它涉及不良实践,根据我所读到的,会产生显着的CPU负载。
未能解决的尝试:
切换到Update()和Time.deltaTime没有任何区别。
我尝试在Update()中不返回,而是在stop被设置时简单地重置timestep为0。没有变化。
在检查器中捣鼓并做一些诸如在刚体上冻结位置或将玩家对象也设置为触发器之类的事情根本没有效果。在游戏运行后更改刚体组件上的任何内容(在碰撞后)都会使立方体立即停止。真的是任何东西,甚至将其质量设置为0。
我还尝试将速度设置为0,结果没有变化。这是有道理的,因为Update()完全被跳过了(顺便说一下,我也用Debug.Log()检查了一下)。
创建一个位于位置(0,0,0)的玩家对象(Cube)。
删除BoxCollider组件。
附加以下C#脚本,Unity会自动添加所需的组件并使其成为刚体碰撞器。
设置isKinematic标志。
在场景中添加另一个Cube,位置为(2,0,0)。
删除BoxCollider组件并添加BoxCollider2D。这将使此立方体成为静态碰撞器。
设置isTrigger标志。
运行场景。
预期行为: 玩家方块加速向其他方块移动,并在触碰到其他方块时停止移动。
观察到的行为: 玩家方块加速向其他方块移动,然后以恒定速度继续移动。
附加实现细节: 我最初通过转换它们的变换来移动所有对象,并且根本没有使用Rigidbodies,因为我不需要碰撞检测。现在我需要,所以我想要Rigidbodies。我深入研究了在线资源,并发现我应该使用rigidbody.MovePosition()而不是transform.Translate()或transform.position。我更改了我的脚本,上述错误出现了。 回到transform.position可以解决问题,但这不是一个好的解决方案,因为它涉及不良实践,根据我所读到的,会产生显着的CPU负载。
未能解决的尝试:
切换到Update()和Time.deltaTime没有任何区别。
我尝试在Update()中不返回,而是在stop被设置时简单地重置timestep为0。没有变化。
在检查器中捣鼓并做一些诸如在刚体上冻结位置或将玩家对象也设置为触发器之类的事情根本没有效果。在游戏运行后更改刚体组件上的任何内容(在碰撞后)都会使立方体立即停止。真的是任何东西,甚至将其质量设置为0。
我还尝试将速度设置为0,结果没有变化。这是有道理的,因为Update()完全被跳过了(顺便说一下,我也用Debug.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;
}
}
busy = true
会禁用整个引擎。此时,对象应该完全静止,因为它不受任何影响。如果我的引擎有问题,立方体在受到影响时会表现异常,但是一旦关闭引擎并且 Unity 的引擎接管后,它就开始表现异常。正如我所说,我的整个引擎都在这段代码中,而且你可以很容易地看到,所有的事情都发生在Update()
中,在设置busy
后就立即返回。在检测到碰撞后发生的任何事情都是由 Unity 引起的(正确)。 - scenia