Dano em Área
Lição 20 de 25 do curso Jogo de Unity: Defesa de Torres da Coddy.
O projétil do Cannon explode onde cai e causa dano a todos os inimigos próximos à explosão, não apenas ao alvo. Physics.OverlapSphere(center, radius) retorna todos os colliders dentro de radius de center: inimigos, mas também o chão e o caminho. Cada collider que tem um IDamageable recebe o dano. O alvo é um deles, já que o projétil cai sobre ele, então não deve receber dano uma segunda vez por conta própria. Uma bomba que empurra todas as caixas ao redor:
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);
}
}
}O raio da explosão é um dado do Cannon, então agora um projétil precisa de mais do que um valor de dano: Launch também recebe o TowerData da torre. O raio de explosão de uma Arrow é 0, então seus disparos continuam atingindo apenas o alvo. O dano continua sendo um argumento separado, já que depende do nível da torre.
Uma explosão mostra ao jogador onde o projétil caiu: uma esfera translúcida tão larga quanto o raio da explosão, que desaparece após um quarto de segundo. Destroy(blast, 0.25f) a destrói após esse atraso, sem precisar criar seu próprio temporizador.
Desafio
MédioOs projéteis de canhão explodem e causam dano a todos os inimigos próximos.
- Em
TowerData, adicionepublic float splashRadius;(CannonData define 1.5).Launchrecebe um terceiro argumento,TowerData data, que a Torre passa. - Ao chegar, se
data.splashRadius > 0, cada IDamageable emPhysics.OverlapSphere(transform.position, data.splashRadius)recebe o dano uma vez; caso contrário, somente o alvo. - Em seguida, exiba ali um
blastPrefabserializado, dimensionado comoVector3.one * data.splashRadius * 2f, e useDestroy(blast, 0.25f).
Pressione “Jogar”: uma explosão de canhão causa dano a vários Grunts agrupados. Depois, pressione “Verificar”.
Experimente você mesmo
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);
}
}
}
Todas as lições de Jogo de Unity: Defesa de Torres
3Estratégia
Dados da TorrePratique por conta própria: Playground de Unity