简体   繁体   English

Unity3D Physical Rigidbody无法检测到碰撞

[英]Unity3D Physics Rigidbody Does Not Detect Collisions

I am building a simple game in unity that involves two players that punch each other. 我正在构建一个统一的简单游戏,其中涉及两个互相冲刺的玩家。 Players can move around the stage and click a button to punch in front of them, the goal being to knock the other player off the stage. 玩家可以在舞台上四处移动,然后单击一个按钮在其前面打孔,目的是将其他玩家从舞台上撞下来。

I got a punching script from this link , but the way it's written is that the punch doesn't interact with other Rigidbodies during the punch animation, collisions are only detected when the punch function is not active. 我从此链接获得了一个穿孔脚本,但其编写方式是,在穿孔动画期间穿孔不与其他Rigidbodies交互,仅当穿孔功能未激活时才检测到碰撞。 It was proposed that work with other Rigidbodies that I use Rigidbody.MovePosition() . 建议使用我使用Rigidbody.MovePosition()其他Rigidbody。 I tried to implement it with MovePosition() but ended up removing the punch animation and putting me farther away from a solution. 我试图用MovePosition()实现它,但最终删除了打孔动画,使我离解决方案更远了。

Here is the punch script 这是打孔脚本

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;
}

and with MovePosition() 并带有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;
}

I am 100% certain that I have the player's physics components set up correctly, the only issue is that there is no collision detection when players punch each other. 我100%地确定我正确设置了球员的物理组件,唯一的问题是,当球员相互冲撞时没有碰撞检测。

Any help is greatly appreciated! 任何帮助是极大的赞赏!

TL;DR : Take the first script and change the transform.position = ...; TL; DR :获取第一个脚本并更改transform.position = ...; to rigidbody.MovePosition (...); rigidbody.MovePosition (...); .

There are two possibilities here: either a) your rigidbody and the target are not configured correctly (for example, one object is a static body), or b) your rigid bodies are never actually intersecting. 这里有两种可能性:a)您的刚体和目标配置不正确(例如,一个对象是静态物体),或b)刚体实际上从未相交。

Ensuring Physics is Actually Properly Set Up 确保物理设置正确

In case you (or another reader) should need to verify that their physics Rigidbodies are properly configured, check: 如果您(或其他读者)需要验证其物理刚体是否正确配置,请检查:

  1. That the colliding game objects are also NOT marked Static at the top right in the inspector, and 在检查器的右上方,碰撞的游戏对象也未标记为“静态”,并且
  2. That the RigidBody Component is not marked Kinematic. RigidBody组件未标记为运动学的。
  3. Finally, verify that the GameObject has a properly configured Collider (Box Collider, Sphere Collider, or Capsule Collider, typically). 最后,验证GameObject是否具有正确配置的对撞机(通常是Box Collider,Sphere Collider或Capsule Collider)。

Determining if Rigid Bodies are Actually Intersecting 确定刚体实际上是相交的

The second issue is just dependent on the objects' transform positions within space. 第二个问题仅取决于对象在空间中的变换位置。 Of course, if you're simulating rigidbody objects with physics, you shouldn't be directly specifying these positions, but using the methods of Rigidbody instead, which is why there was the suggestion of using Rigidbody.MovePosition () . 当然,如果要用物理学模拟刚体对象,则不应直接指定这些位置,而应使用Rigidbody的方法,这就是为什么建议使用Rigidbody.MovePosition ()

Backing up a little and to make sure any future readers are on the same page, these Punch scripts really have nothing to do with collision detection for rigidbodies, per se, and are really just for changing the position of the GameObject relative to its parent. 稍作备份并确保将来有任何读者在同一页面上,这些Punch脚本实际上与刚体的碰撞检测无关,实际上,它们实际上只是用于更改GameObject相对于其父对象的位置。 In other words, the first iteration of the script is just thrusting the fist forward and back over a short time period. 换句话说,脚本的第一次迭代只是在短时间内向前和向后推动拳头。 The issue here is that it directly modifies the transform, which is ill-advised for non-kinematic Rigidbodies. 这里的问题是它直接修改了转换,这对于非运动刚体来说是不明智的。

The issue with the second script, which attempts to rectify direct assignment of the position using the transform, is that it instantly pushes the hand forward (up to point in the first yield return null ), and then retracts the object on the following frame that the coroutine runs. 第二个脚本试图通过转换纠正位置的直接分配的问题是,它立即将手向前推动(直到第一个yield return null ),然后在下一个帧上收回对象协程运行。

Instead, take the first script and change it from using Transform.position = ...; 相反,采用第一个脚本并使用Transform.position = ...;对其进行更改Transform.position = ...; to rigidbody.MovePosition (...); rigidbody.MovePosition (...); . Doing so should bring back the animated movement of the fist. 这样做应恢复拳头的动画动作。 Also if you haven't already, in void Awake () , you should get a reference to the rigid body, and then store it in a member variable for use here. 另外,如果还没有,请在void Awake ()获取对刚体的引用,然后将其存储在成员变量中以供此处使用。

Finally, be aware that MovePosition only interpolates movement if the interpolation property is set to true, and by default, interpolation is false except for character controllers. 最后,请注意,只有在将插值属性设置为true的情况下,MovePosition才会插补运动,默认情况下,除字符控制器外,插值为false。 Even so, your second coroutine does not allow enough time for interpolation to occur. 即使这样,您的第二个协程仍然没有足够的时间进行插值。

The final script might look something like this: 最终脚本可能如下所示:

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;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM