การจัดการการชนด้วยฟิสิกส์มาตรฐาน (2D)

ปรับปรุงหน้า :
วันที่สร้างเพจ :

สภาพแวดล้อมการตรวจสอบ

หน้าต่าง
  • หน้าต่าง 11
บรรณาธิการ Unity
  • ปี 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 เป็นวัตถุ 3 มิติดังนั้นอย่าทําผิดพลาด

Physics 2DBox Collider 2Dเลือกจาก . เนื่องจากสไปรท์นี้เป็นรูปสี่เหลี่ยมผืนผ้า Box จึงถูกเลือก แต่ถ้าเป็นรูปวงกลม ให้เลือกรูปร่างอื่นๆ เช่น วงกลม

ครั้งสุดท้ายฉันต้องการรับข้อมูลเท่านั้นว่าฉันตีหรือไม่ดังนั้นฉันจึงตรวจสอบ "ทําให้มันทริกเกอร์" แต่คราวนี้ฉันจะไม่ทํา สิ่งนี้ทําให้สามารถจัดการการชนกันในฟิสิกส์ได้

Rigidbody 2Dจากนั้นเพิ่มส่วนประกอบของ . คุณสามารถเพิ่มได้จาก "ฟิสิกส์ 2D -> Rigidbody 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 ในขณะที่วัตถุกําลังตีกัน
OnCollisionExit2D เมื่อวัตถุออกจากสถานะการชน

ในทั้งสองกรณีวัตถุฝ่ายตรงข้ามจะได้รับวัตถุของฝ่ายตรงข้ามเป็นอาร์กิวเมนต์ดังนั้นคุณสามารถรับวัตถุของCollision2Dฝ่ายตรงข้ามได้โดยค้นหาCollider2D.gameObjectประเภทของเป้าหมายที่ถูกโจมตีโดย (ศัตรูCollider2D.collider.tagไอเท็ม ฯลฯ )

OnCollisionEnter2Dจากสามเหตุการณ์ข้างต้นและOnCollisionExit2Dเรียกว่าหนึ่งครั้งต่อการชนกัน

OnCollisionStay2D เรียกว่าทุกเฟรมระหว่างการชน แต่เหตุการณ์จะไม่ถูกเรียกอีกต่อไปหลังจากเวลาผ่านไประยะหนึ่งเนื่องจากวัตถุทั้งสองหยุดลง นี่เป็นเพราะมันถือว่าได้เข้าสู่สถานะการนอนหลับและถือว่าเป็นการสูญเสียการประมวลผลเพื่อคํานวณการชนทุกเฟรมกับสิ่งที่ไม่เคลื่อนที่

หากคุณ Rigidbody 2D ไม่ต้องการให้เข้าสู่โหมดสลีป ให้เปลี่ยนโหมดสลีปของพารามิเตอร์เป็น "อย่าสลีป"

หลังจากเปลี่ยนรหัสแล้วให้ตั้งค่าข้อความสําหรับการแสดงข้อมูล

เรียกใช้เกมและย้ายวัตถุด้วยแป้นพิมพ์เพื่อสัมผัสสไปรท์อื่น คุณจะเห็นว่ามีการเรียกฟังก์ชั่นสามอย่างสําหรับแต่ละฟังก์ชัน

โดยวิธีการถ้าคุณสัมผัสวัตถุแล้วหยุดเคลื่อนไหววิธีการจะถูกเรียกในช่วงเวลา OnCollisionStay2D สั้น ๆ คุณควรจะเห็นว่าวิธีการนี้ไม่ได้ถูกเรียกอีกต่อไปหลังจาก OnCollisionStay2D ระยะเวลาหนึ่ง

สิ่งนี้บ่งชี้ว่าคุณได้เข้าสู่สถานะสลีปแล้ว แต่ถ้าคุณต้องการเปลี่ยนเวลาจนกว่าคุณจะเข้าสู่โหมดสลีปนี้คุณสามารถเปลี่ยนได้โดยเลือก "ฟิสิกส์ 2 มิติ" จากการตั้งค่าโครงการและระบุพารามิเตอร์ "เวลาสลีป" เป็นวินาที ไม่สามารถตั้งค่าเป็น 0 ได้ แต่ถ้า OnCollisionStay2D ตั้งค่าให้เล็กลงอย่างไม่มีที่สิ้นสุดวิธีการนั้นจะไม่ถูกเรียก