الهجوم واسع النطاق
الدرس 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) إلى تدميرها بعد ذلك التأخير، من دون الحاجة إلى مؤقت خاص بك.
التحدي
متوسط- في
TowerData، أضِفsplashRadiusمن النوع float واجعله عامًا: القيمة 0 تعني عدم وجود ضرر نطاقي. يضبط CannonData القيمة على 1.5. - غيّر
Projectile.LaunchإلىLaunch(Transform target, int damage, TowerData data)واحتفظ بالبيانات. فيTower، مرّر بيانات البرج. - عند الوصول، إذا كان نصف قطر الضرر النطاقي في البيانات أكبر من 0، فألحِق الضرر بكل مصادم ضمن ذلك النطاق من نقطة الإصابة لديه IDamageable، ويشمل ذلك الهدف، مرة واحدة. ثم أظهِر الانفجار: أنشئ
blastPrefab(وهو GameObject) مُسلسَلًا عند نقطة الإصابة، واضبط حجمه علىVector3.one * data.splashRadius * 2fثم دمّره بعد 0.25 ثانية. إذا لم يوجد ضرر نطاقي، فلن يتضرر سوى الهدف، كما في السابق.
يحتوي العنصر النائب 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);
}
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.