Sát thương lan
Bài học 20 trên 25 trong khóa học Game Unity: thủ thành của Coddy.
Đạn pháo của Cannon phát nổ tại nơi nó rơi xuống và gây sát thương cho mọi kẻ địch gần vụ nổ, không chỉ mục tiêu. Physics.OverlapSphere(center, radius) trả về mọi collider nằm trong phạm vi radius tính từ center: kẻ địch, nhưng cả mặt đất và đường đi nữa. Mỗi collider có IDamageable đều chịu sát thương. Mục tiêu cũng nằm trong số đó vì viên đạn rơi trúng nó, nên bản thân mục tiêu không được chịu sát thương lần thứ hai. Một quả bom đẩy lùi mọi thùng hàng xung quanh:
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);
}
}
}Bán kính lan sát thương là dữ liệu của Cannon, nên giờ đây một viên đạn cần nhiều hơn một con số sát thương: Launch nhận cả TowerData của tháp. Bán kính lan sát thương của Arrow là 0, vì vậy các phát bắn của nó vẫn chỉ trúng riêng mục tiêu. Sát thương vẫn là một đối số riêng vì nó phụ thuộc vào cấp của tháp.
Vụ nổ cho người chơi thấy nơi viên đạn phát nổ: một khối cầu trong suốt có chiều rộng bằng vùng lan sát thương, biến mất sau một phần tư giây. Destroy(blast, 0.25f) hủy nó sau khoảng thời gian đó mà bạn không cần tự tạo bộ đếm thời gian.
Thử thách
Trung bìnhĐạn đại bác phát nổ và gây sát thương cho mọi kẻ địch ở gần.
- Trong
TowerData, thêmpublic float splashRadius;(CannonData đặt giá trị là 1.5).Launchnhận đối số thứ ba làTowerData data, do Tower truyền vào. - Khi đạn đến nơi, nếu
data.splashRadius > 0, mỗi IDamageable trongPhysics.OverlapSphere(transform.position, data.splashRadius)chịu sát thương một lần; nếu không, chỉ mục tiêu chịu sát thương. - Sau đó, hiển thị
blastPrefabđã được tuần tự hóa tại đó, với tỉ lệVector3.one * data.splashRadius * 2f, rồi gọiDestroy(blast, 0.25f).
Nhấn Chơi: vụ nổ của Cannon gây sát thương cho các Grunt tụ lại gần nhau. Sau đó nhấn Kiểm tra.
Tự làm thử
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);
}
}
}
Tất cả bài học trong Game Unity: thủ thành
Tự luyện tập: Playground Unity