Unity3D 物理刚体无法检测碰撞



我正在构建一个简单的统一游戏,涉及两个玩家互相殴打。玩家可以在舞台上移动并点击一个按钮在他们面前打拳,目标是将其他玩家从舞台上击倒。

我从这个链接中得到了一个打孔脚本,但它的编写方式是打孔在打孔动画期间不与其他Rigidbodies交互,只有在打孔功能未激活时才检测到碰撞。有人建议与我使用的其他刚体一起工作Rigidbody.MovePosition().我试图用MovePosition()实现它,但最终删除了 punch 动画,让我离解决方案更远了。

这是打孔脚本

IEnumerator Punch(float time, float distance, Vector3 direction)
{
punching = true;
var timer = 0.0f;
var orgPos = transform.position;
direction.Normalize();
while (timer <= time) {
transform.position = orgPos + (Mathf.Sin(timer / time * Mathf.PI) + 1.0f) * direction;
yield return null;
timer += Time.deltaTime;
}
transform.position = orgPos;
punching = false;
}

MovePosition()

IEnumerator Punch(float time, float distance, Vector3 direction)
{
punching = true;
var timer = 0.0f;
var orgPos = transform.position;
direction.Normalize();
rb.MovePosition(orgPos + direction);
yield return null;
rb.MovePosition(orgPos);
punching = false;
}

我 100% 确定我正确设置了玩家的物理组件,唯一的问题是当玩家互相殴打时没有碰撞检测。

任何帮助将不胜感激!

TL;DR:取第一个脚本,将transform.position = ...;更改为rigidbody.MovePosition (...);

这里有两种可能性:a) 刚体和目标配置不正确(例如,一个对象是静态实体),或者 b) 刚体实际上从未相交。

确保物理场实际设置正确

如果您(或其他读者)需要验证其物理刚体配置是否正确,请检查:

  1. 碰撞的游戏对象在检查器的右上角也没有标记为静态,并且
  2. 刚体组件未标记为运动学。
  3. 最后,验证游戏对象是否具有正确配置的碰撞体(通常为箱形碰撞体、球体碰撞体或胶囊碰撞体)。

确定刚体是否实际相交

第二个问题仅取决于物体在空间中的变换位置。当然,如果你用物理学模拟刚体物体,你不应该直接指定这些位置,而是使用Rigidbody的方法,这就是为什么有人建议使用Rigidbody.MovePosition ()

稍微备份一下,为了确保任何未来的读者都在同一页面上,这些 Punch 脚本本身实际上与刚体的碰撞检测无关,实际上只是为了更改游戏对象相对于其父对象的位置。换句话说,脚本的第一次迭代只是在短时间内向前和向后推拳头。这里的问题是它直接修改了变换,这对于非运动刚体来说是不明智的。

第二个脚本试图使用变换纠正位置的直接分配,它的问题在于它会立即将手向前推(直到第一个yield return null中的点),然后在协程运行的下一帧上收回对象。

相反,采用第一个脚本并将其从使用Transform.position = ...;更改为rigidbody.MovePosition (...);。这样做应该会带回拳头的动画运动。此外,如果您还没有,在void Awake ()中,您应该获得对刚体的引用,然后将其存储在成员变量中以便在此处使用。

最后,请注意,仅当插值属性设置为 true 时,MovePosition 才会插值移动,默认情况下,除字符控制器外,插值为 false。即便如此,第二个协程也不允许有足够的时间进行插值。

最终脚本可能如下所示:

using UnityEngine;
[RequiresComponent (typeof(Rigidbody))]
public class Puncher : MonoBehaviour {
Rigidbody _rb;
bool _isPunching;
void Awake () {
_rb = GetComponent<Rigidbody> ()
}
void Update () {
if (!_isPunching && Input.GetKeyDown(KeyCode.Space)) {
StartCoroutine(Punch(0.5f, 1.25f, transform.forward));
}
}
IEnumerator Punch(float time, float distance, Vector3 direction) {
_isPunching = true;
var timer = 0.0f;
var orgPos = transform.position;
direction.Normalize();
while (timer <= time) {
_rb.MovePosition (orgPos + (Mathf.Sin(timer / time * Mathf.PI) + 1.0f) * direction);
yield return null;
timer += Time.deltaTime;
}
transform.position = orgPos;
_isPunching = false;
}
}

最新更新