Menu
CoddyTech

נזק אזורי

שיעור 14 מתוך 18 בקורס משחק Unity: הגנת מגדלים של Coddy.

פגז התותח מתפוצץ במקום שבו הוא נוחת ופוגע בכל אויב בקרבת הפיצוץ, ולא רק במטרה שלו. Physics.OverlapSphere(center, radius) מחזירה כל קוליידר שנמצא במרחק של עד radius מ־center: אויבים, אבל גם את הקרקע ואת השביל. כל קוליידר שיש לו IDamageable סופג את הנזק. המטרה היא אחד מהם, מכיוון שהפגז נוחת עליה, ולכן אסור לפגוע בה שוב בפני עצמה. פצצה שמעיפה לאחור כל ארגז שנמצא סביבה:

void Explode()
{
    foreach (Collider other in Physics.OverlapSphere(transform.position, blastRadius))
    {
        if (other.TryGetComponent(out Rigidbody body))
        {
            Vector3 away = (body.position - transform.position).normalized;
            body.AddForce(away * push, ForceMode.Impulse);
        }
    }
}

רדיוס הפגיעה ההיקפית הוא חלק מהנתונים של התותח, ולכן קליע זקוק עכשיו ליותר ממספר נזק: Launch מקבלת גם את TowerData של המגדל. רדיוס הפגיעה ההיקפית של חץ הוא 0, ולכן היריות שלו ממשיכות לפגוע רק במטרה שלהן. הנזק נשאר ארגומנט נפרד, מכיוון שהוא תלוי ברמה של המגדל.

פיצוץ מראה לשחקן היכן הפגז התפוצץ: כדור שקוף למחצה, שרוחבו כרוחב הפגיעה ההיקפית, ונעלם לאחר רבע שנייה. Destroy(blast, 0.25f) משמידה אותו לאחר ההשהיה הזאת, בלי שתצטרכו ליצור טיימר משלכם.

challenge icon

אתגר

בינוני
  1. ב־TowerData, הוסף splashRadius מסוג float ציבורי: הערך 0 פירושו שאין פגיעת שטח. ב־CannonData הגדר 1.5.
  2. שנה את Projectile.Launch ל־Launch(Transform target, int damage, TowerData data) ושמור את הנתונים. ב־Tower, העבר את הנתונים של הצריח.
  3. בהגעה, כאשר רדיוס פגיעת השטח של הנתונים גדול מ־0, כל Collider שנמצא בתוך הרדיוס מנקודת הפגיעה ויש לו IDamageable מקבל את הנזק פעם אחת, כולל המטרה. לאחר מכן הצג את הפיצוץ: צור מופע של blastPrefab (GameObject) שעבר סריאליזציה בנקודת הפגיעה, שנה את קנה המידה שלו ל־Vector3.one * data.splashRadius * 2f והשמד אותו אחרי 0.25 שניות. כשאין פגיעת שטח, רק המטרה נפגעת, כמו קודם.

ל־prefab של CannonBall יש את ה־Blast בשדה blastPrefab שלו. לחץ על Play, הצב Cannon במקום שבו האויבים מתקבצים, ואז לחץ על Check.

נסו בעצמכם

using UnityEngine;

public class Projectile : MonoBehaviour
{
    [SerializeField] private float speed = 12f;

    private Transform target;
    private int damage;

    public void Launch(Transform target, int damage)
    {
        this.target = target;
        this.damage = damage;
    }

    void Update()
    {
        if (target == null)
        {
            Destroy(gameObject);
            return;
        }

        transform.position = Vector3.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
        if (transform.position == target.position)
        {
            if (target.TryGetComponent(out IDamageable damageable))
            {
                damageable.TakeDamage(damage);
            }
            Destroy(gameObject);
        }
    }
}
quiz iconבחנו את עצמכם

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

כל השיעורים ביחידה משחק Unity: הגנת מגדלים