範囲攻撃
Coddyの「Unityゲーム:タワーディフェンス」コースのレッスン 20/25。
Cannon の砲弾は着弾地点で爆発し、標的だけでなく爆発の近くにいるすべての敵にダメージを与えます。Physics.OverlapSphere(center, radius) は、center から radius 以内にあるすべてのコライダーを返します。敵だけでなく、地面や経路も含まれます。IDamageable を持つ各コライダーがダメージを受けます。標的もそのうちの1つです。砲弾は標的に着弾するため、標的自身が2回ダメージを受けないようにする必要があります。周囲のすべての木箱を吹き飛ばす爆弾の例:
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);
}
}
}爆発範囲は Cannon のデータなので、弾丸にはダメージ値以外の情報も必要になります。Launch は砲塔の TowerData も受け取ります。Arrow の爆発範囲は 0 なので、その弾はこれまでどおり標的だけに命中します。ダメージは砲塔のレベルによって変わるため、別の引数のままにします。
爆発エフェクトは、砲弾が爆発した場所をプレイヤーに示します。爆発範囲と同じ幅の半透明の球体が、0.25秒後に消えます。Destroy(blast, 0.25f) は指定した遅延の後にオブジェクトを破棄するので、自分でタイマーを用意する必要はありません。
チャレンジ
中級大砲の砲弾が爆発し、近くにいるすべての敵にダメージを与えます。
TowerDataにpublic float splashRadius;を追加します(CannonDataでは1.5に設定します)。Launchは3つ目の引数TowerData dataを受け取り、Towerから渡します。- 到着時に
data.splashRadius > 0なら、Physics.OverlapSphere(transform.position, data.splashRadius)内の各IDamageableに1回ずつダメージを与えます。それ以外の場合は、対象だけにダメージを与えます。 - 次に、シリアライズされた
blastPrefabをその場所に表示し、Vector3.one * data.splashRadius * 2fの大きさにして、Destroy(blast, 0.25f)を実行します。
「プレイ」を押します。Cannonの爆発で、密集したGruntにダメージを与えます。次に「確認」を押します。
自分で試してみよう
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);
}
}
}
Unityゲーム:タワーディフェンスのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド