使用標準物理場進行碰撞處理 (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 無限小,則不會調用方法本身。