ממשקים ו-TryGetComponent
חלק מהיחידה ארכיטקטורת משחקים ב-Unity במסלול ה-Unity של Coddy. שיעור 7 מתוך 50.
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 מדווחת באופן שונה על מחלקה חסרה ועל ממשק חסר. בעורך, GetComponent<Rigidbody>() על אובייקט שאין לו Rigidbody מחזירה null מזויף של Unity: == null הוא true, אבל ?. לא מזהה אותו והקריאה זורקת MissingComponentException. לממשק אין null מזויף: GetComponent<IDamageable>() מחזירה null אמיתי של C#, ולכן גם == null וגם ?. פועלים עליו. TryGetComponent מייתרת את הצורך לבדוק זאת בשני המקרים, והיא לא מקצה זיכרון בעורך כשהרכיב חסר.
אתגר
קלמגדל הלייזר מסתובב באמצעות החצים שמאלה וימינה, ומקש הרווח מפעיל את Fire() שבקובץ Laser.cs. כתבו את Fire. שגרו קרן מהמגדל בכיוון שאליו הוא פונה, באורך של range יחידות (החלונית Inspector קובעת את הערך ל-10), ואז:
- אם הקרן פוגעת במשהו שיש לו IDamageable, קראו לו ל-
TakeDamage(damage)ורשמו ביומן אתHitואת שם האובייקט, למשלHit Robot. - אם לדבר אין IDamageable אבל יש לו Rigidbody, דחפו אותו באמצעות
AddForce(transform.forward * push, ForceMode.Impulse)ורשמו ביומן אתPushedואת שמו. - כל דבר אחר רושם ביומן את
Blocked byואת שמו, למשלBlocked by Pillar. קרן שלא פוגעת בכלום רושמת ביומןMissed.
השתמשו ב-TryGetComponent בשתי הבדיקות. הקבצים IDamageable.cs, Robot.cs ו-Balloon.cs מוכנים. לחצו על הפעלה וירו לכל הכיוונים, ואז לחצו על בדיקה.
נסו בעצמכם
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רכיבים, לא היררכיות
רכיבים קטניםסקריפט בסיס לאויברכיבים מופשטיםרכיבים שעובדים יחדסיכום: צריח מודולרי