ממשקים ו-TryGetComponent
חלק מהיחידה ארכיטקטורת משחקים ב-Unity במסלול ה-Unity של Coddy. שיעור 8 מתוך 64.
TryGetComponent מחפשת רכיב ומציינת אם מצאה אחד, בקריאה אחת. היא עובדת גם עם ממשקים, ולכן זו הדרך המקובלת לשאול כל דבר שנתקלת בו אם אפשר לפגוע בו. המוקש הזה פוגע בכל מה שסביבו שמממש את IDamageable:
public class Mine : MonoBehaviour
{
public float radius = 3f;
public int damage = 5;
void OnTriggerEnter(Collider other)
{
foreach (Collider c in Physics.OverlapSphere(transform.position, radius))
{
if (c.TryGetComponent(out IDamageable target))
{
target.TakeDamage(damage);
}
}
Destroy(gameObject);
}
}out IDamageable target מכריזה על המשתנה בתוך הקריאה. TryGetComponent מחזירה true וממלאת את target כאשר לאובייקט יש רכיב שמממש את IDamageable; אחרת היא מחזירה false, ו-target הוא null. היא בודקת רק את אותו אובייקט, אף פעם לא את ההורה או את הילדים שלו.
GetComponent מדווחת באופן שונה על מחלקה חסרה ועל ממשק חסר. ב-Editor, קריאה ל-GetComponent<Rigidbody>() באובייקט שאין בו Rigidbody מחזירה ערך null מזויף של Unity: הביטוי == null הוא true, אבל ?. לא מזהה אותו והקריאה גורמת ל-MissingComponentException. לממשק אין ערך null מזויף: GetComponent<IDamageable>() מחזירה ערך null אמיתי של C#, ולכן גם == null וגם ?. פועלים עליו. TryGetComponent מונעת את ההתלבטות בשני המקרים, ולא מקצה זיכרון ב-Editor כשהרכיב חסר.
אתגר
קלכתוב את Fire() בתוך Laser: קרן אחת, ארבע תוצאות.
- הפעל את
Physics.Raycastמהמגדל לאורךtransform.forward, למרחקrange. במקרה של החטאה, רשום ביומן אתMissed. - אם מתקיים
hit.collider.TryGetComponent(out IDamageable target), קרא ל־TakeDamage(damage)ורשום ביומן את"Hit " + hit.collider.name. - אחרת, אם יש לו
Rigidbody, הפעל אתAddForce(transform.forward * push, ForceMode.Impulse)ורשום ביומן את"Pushed "בתוספת השם; אחרת, רשום ביומן את"Blocked by "בתוספת השם.
לחץ על „שחק”, הסתובב וירה לכל הכיוונים. לאחר מכן לחץ על „בדיקה”.
נסו בעצמכם
using UnityEngine;
using UnityEngine.InputSystem;
public class Laser : MonoBehaviour
{
public float range = 10f;
public int damage = 1;
public float push = 5f;
public float turnSpeed = 90f;
private InputAction moveAction;
void Start()
{
moveAction = InputSystem.actions.FindAction("Move");
}
void Update()
{
float turn = moveAction.ReadValue<Vector2>().x;
transform.Rotate(0f, turn * turnSpeed * Time.deltaTime, 0f);
if (Keyboard.current.spaceKey.wasPressedThisFrame)
{
Fire();
}
}
void Fire()
{
// הטל קרן קדימה באורך של range יחידות, וטפל במה שהיא פוגעת בו
}
}
כל השיעורים ביחידה ארכיטקטורת משחקים ב-Unity
1רכיבים, לא היררכיות
רכיבים קטניםסקריפט בסיסי לאויברכיבים מופשטיםרכיבים שפועלים יחדחזרה: צריח מודולריחזרה: תותח כפול4נתונים שעברו סריאליזציה
מחלקות שניתנות לסריאליזציהרשימות ב־Inspectorטיפוסי Enum ב־Inspectorחזרה: טבלת שללהגרלת השלל2ממשקים ב-Unity
IDamageableממשקים ו-TryGetComponentGetComponentsסיכום: מקש אינטראקציהסיכום: הקרוב ביותר בטווחתרגלו בעצמכם: Unity אונליין