Menu
CoddyTech

Eventi C# in Unity

Fa parte della sezione Architettura dei giochi in Unity del percorso Unity di Coddy. Lezione 10 di 50.

Quando il punteggio cambia, ci sono diverse cose interessate: il testo del punteggio, un suono, un obiettivo. Se ScoreKeeper chiama ognuna di esse, gli serve un campo per ciascuna e ogni nuova funzionalità significa modificarlo. Un evento ribalta la situazione: ScoreKeeper annuncia la modifica e chi è interessato si iscrive. Conosci event e Action da C#. In Unity, il publisher e i suoi listener sono componenti, di solito su GameObject diversi:

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, sul testo dell'HUD
public ScoreKeeper keeper;
public TMP_Text label;

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

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

Action<int> significa che ogni listener è un metodo che accetta un int, in questo caso il nuovo punteggio. Invoke chiama ogni metodo iscritto, nell'ordine in cui si è iscritto. Se non ci sono listener, l'evento è null, quindi una semplice chiamata OnScoreChanged(score) genererebbe un'eccezione NullReferenceException, mentre ?. salta la chiamata. La parola chiave event limita gli altri script a += e -=: in ScoreLabel, keeper.OnScoreChanged(5) o keeper.OnScoreChanged = null non compila.

ScoreKeeper non ha un campo per l'etichetta e non sa nemmeno che esiste. Un contatore di combo o un riproduttore di suoni si iscrive allo stesso modo e ScoreKeeper resta com'è; inoltre, una scena di test senza HUD viene eseguita senza errori. Un listener trova il publisher tramite un riferimento nell'Inspector, come qui, o in qualsiasi altro modo conosciuto, ad esempio GetComponent o un singleton. Rimuovere un listener con -= è importante quando gli oggetti vengono distrutti: è l'argomento della prossima lezione.

challenge icon

Sfida

Facile

La combo del combattente aumenta a ogni colpo con la barra spaziatrice e torna a 0 dopo comboWindow (1) secondo senza colpi. Al momento Fighter.cs imposta direttamente il testo della combo e la dimensione della fiamma, quindi serve un campo per ciascuno. Inverti la situazione con un evento:

  • In Fighter.cs, dichiara un evento pubblico chiamato OnComboChanged che passa la combo (un int). Attivalo con la nuova combo ogni volta che questa cambia, incluso quando viene azzerata a 0, e assicurati che un colpo non causi errori quando nessuno è in ascolto.
  • Elimina i campi comboText e flame di Fighter e le righe che li usano: Fighter non sa nulla dell'HUD.
  • In ComboText.cs e ComboFlame.cs, sottoscrivi i loro metodi Show e Grow all'evento del combattente in Start(). Entrambi hanno un campo fighter, collegato nella scena.

Premi Play, colpisci il sacco con la barra spaziatrice alcune volte, aspetta un secondo, poi premi Check.

Provalo tu

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;
            }
        }
    }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Architettura dei giochi in Unity