Ricompense
Lezione 10 di 18 del corso Gioco Unity: difesa della torre di Coddy.
Ogni nemico abbattuto da una torre paga la propria reward. L'Enemy segnala l'uccisione come segnala il raggiungimento della base, con un evento statico, Killed, e il GameManager ascolta e aggiunge il denaro.
Un'uccisione deve essere pagata una sola volta. Destroy non rimuove un oggetto immediatamente: l'operazione avviene alla fine del frame e, fino ad allora, l'oggetto è ancora in gioco. Due colpi possono andare a segno nello stesso frame e il secondo trova un nemico con 0 punti salute che è ancora lì. Se TakeDamage segnala un'uccisione ogni volta che la salute è pari o inferiore a 0, il secondo colpo paga di nuovo. Un gioco con palloncini e freccette presenta la stessa insidia, che si può evitare con un bool:
public void Pop()
{
if (popped)
{
return;
}
popped = true;
Popped?.Invoke(this);
Destroy(gameObject);
}Il nemico non ha bisogno di un bool aggiuntivo, poiché la sua salute indica già se è morto: una chiamata a TakeDamage che trova la salute pari o inferiore a 0 non ha più nulla da fare.
Sfida
Medio- In
Enemy, dichiara un evento statico pubblicoKilled(Action<Enemy>). Genera l'evento passando il nemico quando TakeDamage porta la sua salute a 0 o meno, subito prima di distruggerlo. - Una uccisione viene pagata una sola volta: quando TakeDamage viene chiamato su un nemico la cui salute è già pari o inferiore a 0, non fa nulla.
- In
GameManager, aggiungipublic void Earn(int amount), che incrementa il denaro e lo mostra. Iscriviti aEnemy.Killedaccanto a ReachedBase e guadagna larewarddel nemico ucciso.
Premi Play e guarda il denaro aumentare mentre le torri lavorano, poi premi Check.
Provalo tu
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);
}
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.