运动学刚体自行移动
本文关键字:移动 运动学 | 更新日期: 2023-09-27 18:01:52
在我的2D Unity游戏中有一个非常奇怪的问题,我能够将其简化为以下核心问题/最小复制测试用例。按照以下步骤复制(Unity 5.1.1f1):
- 在位置
(0,0,0)
创建一个玩家对象(Cube)。 - 移除
BoxCollider
组件 - 附加以下
C#
脚本,Unity将自动添加所需的组件,从而使其成为刚体碰撞器。 - 设置
isKinematic
标志。 - 添加另一个Cube到场景位置
(2,0,0)
。 - 移除
BoxCollider
组件并添加BoxCollider2D
。这使得这个立方体成为一个静态碰撞器。 - 设置
isTrigger
标志 - 运行场景
预期行为:
玩家立方体加速冲向另一个立方体,一旦碰到它就停止移动。
所观察到的行为:
玩家方块加速冲向另一个方块,然后继续匀速移动。
附加实现细节:
我最初通过转换它们的变换来移动所有对象,并且根本没有使用刚体,因为我不需要碰撞检测。现在我想要刚体。我潜入网上资源,发现我应该使用rigidbody.MovePosition()
而不是transform.Translate()
或transform.position
。我修改了脚本,出现了上面的错误。
回到transform.position
修复了这个问题,但这不是一个好的解决方案,因为它涉及坏的做法,根据我所读到的,产生显著的CPU负载。
尝试解决失败:
- 切换到
Update()
和Time.deltaTime
没有任何影响。 - 我试着不在
Update()
中返回,而是简单地将timestep
重置为0
,而stop
设置。没有变化。 摆弄检查器、冻结刚体上的位置或将玩家对象设置为触发器都不会产生任何效果。当游戏运行(在碰撞之后)时改变刚体组件上的任何内容将使立方体立即停止。几乎任何东西,甚至将其质量设置为0。 - 我也尝试将
velocity
设置为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;
}
}
解决方案
这是Unity 5.1.1f1中的一个错误,并在5.1.1p2和更高版本的补丁中修复。
点击这里:http://unity3d.com/unity/qa/patch-releases?version=5.1
<标题>发生了什么事?您甚至可以将问题减少到单个MovePosition
调用。MovePosition
使用物理引擎来移动对象。因此,Unity计算在下一次物理更新中到达目标位置所需的速度。版本5.1.1f1无法在到达位置后将速度重置为零,因此物体将继续以计算的速度移动。