使用标准物理场进行碰撞处理 (2D)

更新页 :
页面创建日期 :

验证环境

窗户
  • 视窗 11
统一编辑器
  • 2021.3.3f1
输入系统包
  • 1.3.0

此提示的先决条件

作为此提示描述的前提,已预先进行了以下设置。

起先

此提示放置两个对象,以便您可以实现操作一个对象的行为,并在另一个对象接触时使用 Unity 的标准物理来推动另一个对象。

顺便说一下,大多数设置与上一篇文章“确定对象是否相互碰撞(2D)”中所述的过程相同。

制备

这里的程序与前面的提示 几乎相同,所以让我们顺利进行。

创建项目后,准备两个将成为对象的精灵图像并添加它们。 名称分别为“UnityTips”和“UnityTips_2”。

通过将两个图像文件拖放到视图中来添加它们。

添加脚本以使用键盘移动左侧对象。 脚本名称 Player 为 。

using UnityEngine;
using UnityEngine.InputSystem;

public class Player : MonoBehaviour
{
  // 一定時間ごとに呼ばれます
  void FixedUpdate()
  {
    // キーボードの情報を取得
    var keyboard = Keyboard.current;

    // スプライトの移動処理
    if (keyboard.leftArrowKey.isPressed)
    {
      transform.Translate(-0.1f, 0, 0, Space.World);
    }
    if (keyboard.rightArrowKey.isPressed)
    {
      transform.Translate(0.1f, 0, 0, Space.World);
    }
    if (keyboard.upArrowKey.isPressed)
    {
      transform.Translate(0, 0.1f, 0, Space.World);
    }
    if (keyboard.downArrowKey.isPressed)
    {
      transform.Translate(0, -0.1f, 0, Space.World);
    }
  }
}

附加到要对其运行脚本的对象。

运行游戏并检查它是否适用于键盘上的光标键。

最后,放置一个文本对象以显示碰撞检测状态。 对象名称 TextState 为 。

碰撞处理设置

从这里,您可以配置与碰撞相关的设置。

首先,选择要移动的对象“UnityTips”,然后从检查器中单击“添加组件”。 从 Physics 2D 列表中选择。 Physics 是一个 3D 对象,所以不要搞错。

Physics 2DBox Collider 2D从中选择。 由于此子画面是矩形的,因此会选择Box,但如果它是圆形的,例如,请选择其他形状,例如圆形。

上次,我只想获取有关我是否击中它的信息,所以我选中了“让它触发”,但这次我不会。 这使得物理学中的碰撞处理成为可能。

Rigidbody 2D然后添加 的组件。 您可以从“物理 2D -> 刚体 2D”中添加它。 Rigidbody为对象提供物理信息Collider,还可以确定与具有 的对象的碰撞。

将重力刻度设置为 0 以防止在以下自由落体。

同样,将组件添加到另一个对象“UnityTips_2”以标记 Box Collider 2D 命中。

另外,这次要借助对手的力量移动,Rigidbody 2D 所以加上. 重力刻度应为 0。

仅此而已。 目前不需要任何程序。 运行游戏并尝试触摸另一个对象。

我想你可以确认,如果你这样推对手,对手会表现得好像他被推了一样。 使用标准函数的物理特性非常容易,因为不需要程序。

防止物体旋转

当你触摸它时,你可以看到,但如果命中点稍微移动,每个对象都会旋转。 作为游戏,它经常变得不自然,因此您需要对其进行设置,使其不旋转。

Rigidbody 2D 该组件在“约束”中有一个名为“固定旋转”的项目,因此请检查 Z。 现在你可以工作,让它不旋转。 尝试将其设置为两个对象并运行游戏进行检查。

我想你可以确定,无论你从什么角度推动它,它都不会旋转。

当物体相互撞击时做某事

例如,您可能希望实现一颗子弹,在推动对手的同时击中敌人,同时降低敌人的生命值。 这与前面的提示 相同,因为事件会发生,因此您可以处理它。

Player 打开脚本并使用如下方式添加每个字段和方法:

using System;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class Player : MonoBehaviour
{
  /// <summary>状態表示用テキストオブジェクト。</summary>
  [SerializeField] private Text TextState;

  // 中略

  /// <summary>衝突した瞬間に呼ばれます。</summary>
  /// <param name="partner">衝突した相手のコリジョン情報。</param>
  private void OnCollisionEnter2D(Collision2D partner)
  {
    TextState.text = $"OnCollisionEnter2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
  }

  /// <summary>衝突している間呼ばれます。ただしスリープモードになった場合は呼ばれません。</summary>
  /// <param name="partner">衝突した相手のコリジョン情報。</param>
  private void OnCollisionStay2D(Collision2D partner)
  {
    TextState.text = $"OnCollisionStay2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
  }

  /// <summary>衝突状態でなくなったタイミングで呼ばれます。</summary>
  /// <param name="partner">衝突した相手のコリジョン情報。</param>
  private void OnCollisionExit2D(Collision2D partner)
  {
    TextState.text = $"OnCollisionExit2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
  }
}

由于我们想要显示有关它是否被击中的信息,因此我们可以将其显示在文本对象中,如下所示。

/// <summary>状態表示用テキストオブジェクト。</summary>
[SerializeField] private Text TextState;

碰撞检测过程描述如下。

/// <summary>衝突した瞬間に呼ばれます。</summary>
/// <param name="partner">衝突した相手のコリジョン情報。</param>
private void OnCollisionEnter2D(Collision2D partner)
{
  TextState.text = $"OnCollisionEnter2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
}

/// <summary>衝突している間呼ばれます。ただしスリープモードになった場合は呼ばれません。</summary>
/// <param name="partner">衝突した相手のコリジョン情報。</param>
private void OnCollisionStay2D(Collision2D partner)
{
  TextState.text = $"OnCollisionStay2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
}

/// <summary>衝突状態でなくなったタイミングで呼ばれます。</summary>
/// <param name="partner">衝突した相手のコリジョン情報。</param>
private void OnCollisionExit2D(Collision2D partner)
{
  TextState.text = $"OnCollisionExit2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
}

前面的提示类似------,但方法名称现在是“OnCollision------2D”而不是“OnTrigger2D”。

Rigidbody 2D 当一个对象与另一个具有 . 的对象发生 Collider 2D 碰撞时,会发生上述每个事件。 这将允许您确定和处理它是否正确。

有三个事件,每个事件在以下时间调用。

OnCollisionEnter2D 当物体相互撞击时
OnCollisionStay2D 当物体相互撞击时
碰撞出口2D 当对象离开碰撞状态时

在这两种情况下,对手对象接收对手的对象作为参数,因此您可以通过查找Collider2D.gameObject击中的目标类型(敌人、Collider2D.collider.tag物品等)来获取对手的对象Collision2D

OnCollisionEnter2D以上三个事件中,每次OnCollisionExit2D碰撞调用一次。

OnCollisionStay2D 在碰撞期间每帧调用一次,但在两个对象都停止后经过一定时间后不再调用该事件。 这是因为它被认为已进入睡眠状态,并且计算与不移动的东西的每一帧碰撞被认为是浪费处理。

如果 Rigidbody 2D 不希望它进入睡眠状态,请将参数的睡眠模式更改为“不睡眠”。

更改代码后,设置用于显示信息的文本。

运行游戏并使用键盘移动对象以触摸另一个精灵。 您可以看到为每个函数调用了三个函数。

顺便说一下,如果您触摸一个对象然后停止移动,则会在短时间内调用 OnCollisionStay2D 该方法。 您应该能够看到该方法在一段时间后 OnCollisionStay2D 不再被调用。

这表示您已进入睡眠状态,但如果您想更改进入此睡眠之前的时间,您可以通过从项目设置中选择“2D Physics”并指定“睡眠时间”参数(以秒为单位)来更改它。 它不能设置为 0,但如果设置为 OnCollisionStay2D 无限小,则不会调用方法本身。