Menu
CoddyTech

Les événements C# dans Unity

Fait partie de la section Architecture de jeu dans Unity du Journey Unity de Coddy. Leçon 12 sur 64.

Lorsque le score change, plusieurs éléments sont concernés : le texte du score, un son, un succès. Si ScoreKeeper appelle chacun d’eux, il lui faut un champ pour chacun, et chaque nouvelle fonctionnalité implique de le modifier. Un événement inverse la situation : ScoreKeeper annonce le changement, et ceux qui sont concernés s’abonnent.

Deux mots de C# permettent cela. Action<int> est le type d’une méthode qui prend un int et ne renvoie rien. Un event de ce type est une liste de telles méthodes : un autre code ajoute sa méthode avec +=, et le propriétaire les appelle toutes avec Invoke. En C# classique :

using System;

class Alarm
{
    public event Action<int> Rang;

    public void Ring(int hour)
    {
        Rang?.Invoke(hour);
    }
}

class Sleeper
{
    public void WakeUp(int hour)
    {
        Console.WriteLine("Up at " + hour);
    }
}

// ailleurs
Alarm alarm = new Alarm();
Sleeper sleeper = new Sleeper();
alarm.Rang += sleeper.WakeUp;
alarm.Ring(7);   // Debout à 7

Dans Unity, l’émetteur et ses abonnés sont des composants, généralement sur différents GameObjects :

using System;
using UnityEngine;

public class ScoreKeeper : MonoBehaviour
{
    public event Action<int> OnScoreChanged;
    private int score;

    public void AddPoints(int points)
    {
        score += points;
        OnScoreChanged?.Invoke(score);
    }
}
// ScoreLabel.cs, sur le texte du HUD
public ScoreKeeper keeper;
public TMP_Text label;

void Start()
{
    keeper.OnScoreChanged += ShowScore;
}

void ShowScore(int score)
{
    label.text = "Score: " + score;
}

Action<int> signifie que chaque abonné est une méthode qui prend un int, ici le nouveau score. Invoke appelle toutes les méthodes abonnées, dans l’ordre où elles se sont abonnées. Sans abonné, l’événement vaut null, donc un simple OnScoreChanged(score) déclencherait une NullReferenceException, tandis que ?. ignore l’appel. Le mot-clé event limite les autres scripts à += et -= : dans ScoreLabel, keeper.OnScoreChanged(5) ou keeper.OnScoreChanged = null ne compile pas.

ScoreKeeper n’a pas de champ pour l’étiquette et ne sait pas qu’elle existe. Un compteur de combo ou un lecteur audio s’abonne de la même manière, et ScoreKeeper reste inchangé ; une scène de test sans HUD s’exécute sans erreur. Un abonné trouve l’émetteur grâce à une référence dans l’Inspector, comme ici, ou par n’importe quel moyen que tu connais, par exemple GetComponent ou un singleton. Retirer un abonné avec -= devient important une fois que les objets sont détruits, ce qui sera le sujet de la prochaine leçon.

challenge icon

Défi

Facile

Fais annoncer son combo au combattant.

  1. Dans Fighter.cs, ajoute using System; et public event Action<int> OnComboChanged;.
  2. Remplace les lignes qui utilisent comboText et flame par OnComboChanged?.Invoke(combo);, et supprime les deux champs.
  3. Dans le Start() de ComboText et de ComboFlame, écris fighter.OnComboChanged += Show; et += Grow;.

Appuie sur « Jouer » et appuie plusieurs fois sur Espace : le combo augmente, puis s’efface. Ensuite, appuie sur « Vérifier ».

Essayez vous-même

using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;

public class Fighter : MonoBehaviour
{
    public float comboWindow = 1f;
    public TMP_Text comboText;
    public Transform flame;
    private int combo;
    private float sinceHit;

    void Update()
    {
        if (Keyboard.current.spaceKey.wasPressedThisFrame)
        {
            combo++;
            sinceHit = 0f;
            comboText.text = "Combo x" + combo;
            flame.localScale = Vector3.one * (0.5f + 0.25f * combo);
        }
        else if (combo > 0)
        {
            sinceHit += Time.deltaTime;
            if (sinceHit > comboWindow)
            {
                combo = 0;
                comboText.text = "";
                flame.localScale = Vector3.one * 0.5f;
            }
        }
    }
}

Toutes les leçons de Architecture de jeu dans Unity

Entraînez-vous par vous-même : Playground Unity