טיפול בהתנגשות עם פיזיקה סטנדרטית (2D)

עודכן דף :
תאריך יצירת דף :

סביבת אימות

חלונות
  • חלונות 11
עורך Unity
  • 2021.3.3F1
חבילת מערכת קלט
  • 1.3.0

תנאים מוקדמים לטיפ זה

ההגדרות הבאות נקבעו מראש כהנחת יסוד לתיאור עצה זו.

בהתחלה

עצה זו ממקמת שני אובייקטים כך שתוכל ליישם את ההתנהגות של מניפולציה של אובייקט אחד ושימוש בפיזיקה הסטנדרטית של יוניטי כדי לדחוף את השני כאשר הוא בא במגע עם השני.

אגב, רוב ההגדרות זהות להליך המתואר במאמר הקודם "קביעת אם אובייקטים מתנגשים זה בזה (2D)".

הכנה

ההליך כאן כמעט זהה לטיפים הקודמים , אז בואו נזרום אותו בצורה חלקה.

לאחר יצירת הפרויקט, הכינו שתי תמונות ספרייט שיהיו אובייקטים והוסיפו אותן. השמות הם "UnityTips" ו-"UnityTips_2" בהתאמה.

הוסף שני קובצי תמונה על-ידי שחרורם בתצוגה.

הוסף קובץ Script כדי להזיז את האובייקט השמאלי באמצעות לוח המקשים. שם 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);
    }
  }
}

צרף לאובייקט שבו ברצונך להפעיל את קובץ ה- Script.

הפעל את המשחק ובדוק אם הוא פועל עם מקשי הסמן בלוח המקשים.

לבסוף, מקם אובייקט טקסט כדי להציג את מצב זיהוי ההתנגשות. שם TextState האובייקט הוא .

הגדרות טיפול בהתנגשות

מכאן, תוכל להגדיר את ההגדרות הקשורות להתנגשויות.

ראשית, בחר את האובייקט שברצונך להעביר, "UnityTips", ולחץ על "הוסף רכיב" מהמפקח. בחר מתוך Physics 2D הרשימה. Physics הוא אובייקט תלת ממדי, אז אל תטעו.

Physics 2DBox Collider 2D בחר מתוך . מכיוון שספרייט זה הוא מלבני, התיבה נבחרת, אך אם היא בצורת עיגול, לדוגמה, בחר צורות אחרות כגון עיגול.

בפעם הקודמת רציתי לקבל מידע רק אם פגעתי בו או לא, אז בדקתי "Make it trigger", אבל הפעם לא. זה מאפשר טיפול בהתנגשויות בפיזיקה.

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 פרק זמן מסוים.

הדבר מציין שהזנת מצב שינה, אך אם ברצונך לשנות את השעה עד שתיכנס לשינה זו, תוכל לשנות אותה על-ידי בחירה באפשרות "פיזיקה דו-ממדית" מהגדרות הפרויקט וציון הפרמטר "זמן שינה" תוך שניות. לא ניתן להגדיר אותו ל-0, אך אם הוא OnCollisionStay2D מוגדר כקטן עד אינסוף, השיטה עצמה לא תיקרא.