Récompenses
Leçon 10 sur 18 du cours Jeu Unity : défense de tours de Coddy.
Chaque ennemi qu’une tour élimine rapporte sa reward. L’Enemy signale l’élimination comme il signale l’arrivée à la base, au moyen d’un événement statique, Killed, et le GameManager écoute cet événement et ajoute l’argent.
Une élimination ne doit être récompensée qu’une seule fois. Destroy ne supprime pas un objet immédiatement : cela se produit à la fin de la frame, et jusque-là, l’objet est toujours dans le jeu. Deux tirs peuvent toucher pendant la même frame, et le second trouve un ennemi à 0 point de vie qui est toujours présent. Si TakeDamage signale une élimination chaque fois que la santé est à 0 ou moins, ce second tir rapporte à nouveau une récompense. Un jeu de ballons avec des fléchettes présente le même piège, et un booléen permet de l’éviter :
public void Pop()
{
if (popped)
{
return;
}
popped = true;
Popped?.Invoke(this);
Destroy(gameObject);
}L’ennemi n’a pas besoin d’un booléen supplémentaire, puisque sa santé indique déjà s’il est mort : un appel à TakeDamage qui trouve une santé à 0 ou moins n’a plus rien à faire.
Défi
Moyen- Dans
Enemy, déclare un événement statique publicKilled(Action<Enemy>). Déclenche-le avec l’ennemi lorsque TakeDamage fait tomber sa santé à 0 ou moins, juste avant de le détruire. - Une élimination ne rapporte qu’une seule fois : lorsque TakeDamage est appelé sur un ennemi dont la santé est déjà à 0 ou moins, il ne se passe rien.
- Dans
GameManager, ajoutepublic void Earn(int amount), qui ajoute la somme à l’argent et l’affiche. Abonne-toi àEnemy.Killedà côté de ReachedBase et ajoute larewardde l’ennemi éliminé.
Appuie sur Play et regarde l’argent augmenter pendant que les tours fonctionnent, puis clique sur Check.
Essayez vous-même
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);
}
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.