範囲攻撃
Coddyの「Unityゲーム:タワーディフェンス」コースのレッスン 14/18。
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 floatsplashRadiusを追加します。0なら範囲攻撃なしです。CannonDataには1.5を設定します。Projectile.LaunchをLaunch(Transform target, int damage, TowerData data)に変更し、dataを保持します。Towerでは、タワーのdataを渡します。- 着弾時、dataの範囲攻撃の半径が0より大きい場合、着弾地点からその半径以内にあるIDamageableを持つすべてのコライダーに、対象も含めて1回ずつダメージを与えます。続いて爆発エフェクトを表示します。シリアライズされた
blastPrefab(GameObject)を着弾地点にインスタンス化し、Vector3.one * data.splashRadius * 2fにスケールして、0.25秒後に破棄します。範囲攻撃がない場合は、以前と同様に対象だけがダメージを受けます。
CannonBallプレハブのblastPrefabにはBlastが設定されています。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);
}
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。