Recompensas
Lección 10 de 18 del curso Juego de Unity: defensa de torres de Coddy.
Cada enemigo que una torre derriba paga su reward. Enemy informa de la eliminación igual que informa de que ha llegado a la base, mediante un evento estático, Killed, y GameManager lo escucha y añade el dinero.
Una eliminación debe pagarse una sola vez. Destroy no elimina un objeto de inmediato: lo hace al final del fotograma, y hasta entonces sigue en el juego. Dos disparos pueden impactar en el mismo fotograma, y el segundo encuentra a un enemigo con 0 de salud que todavía sigue ahí. Si TakeDamage informa de una eliminación cada vez que la salud está en 0 o menos, ese segundo disparo vuelve a pagar. Un juego de globos con dardos tiene la misma trampa, y un bool la evita:
public void Pop()
{
if (popped)
{
return;
}
popped = true;
Popped?.Invoke(this);
Destroy(gameObject);
}El enemigo no necesita ningún bool adicional, ya que su salud ya indica si está muerto: un TakeDamage que encuentra la salud en 0 o menos no tiene nada más que hacer.
Desafío
Intermedio- En
Enemy, declara un evento estático públicoKilled(Action<Enemy>). Actívalo con el enemigo cuando TakeDamage reduzca su salud a 0 o menos, justo antes de destruirlo. - Una eliminación se recompensa una sola vez: cuando se llama a TakeDamage en un enemigo cuya salud ya está en 0 o menos, no hace nada.
- En
GameManager, añadepublic void Earn(int amount), que suma dinero y lo muestra. Suscríbete aEnemy.Killedjunto a ReachedBase y gana larewarddel enemigo eliminado.
Pulsa Jugar y observa cómo aumenta el dinero mientras trabajan las torres; después, pulsa Comprobar.
Pruébalo tú mismo
using System;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour, IDamageable
{
public static readonly List<Enemy> All = new List<Enemy>();
public static event Action<Enemy> ReachedBase;
public EnemyData data;
public Transform[] waypoints;
private int next = 1;
private int health;
void Awake()
{
health = data.maxHealth;
}
void OnEnable()
{
All.Add(this);
}
void OnDisable()
{
All.Remove(this);
}
void Update()
{
Vector3 target = waypoints[next].position;
transform.position = Vector3.MoveTowards(transform.position, target, data.speed * Time.deltaTime);
if (transform.position == target)
{
next++;
if (next == waypoints.Length)
{
ReachedBase?.Invoke(this);
Destroy(gameObject);
}
}
}
public void TakeDamage(int amount)
{
health -= amount;
if (health <= 0)
{
Destroy(gameObject);
}
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.