Menu
CoddyTech

Zdarzenia C# w Unity

Część sekcji Architektura gier w Unity ścieżki Unity w Coddy. Lekcja 10 z 50.

Gdy wynik się zmienia, kilka rzeczy jest tym zainteresowanych: tekst wyniku, dźwięk, osiągnięcie. Jeśli ScoreKeeper wywołuje każdą z nich, potrzebuje pola dla każdej, a każda nowa funkcja oznacza konieczność jego edycji. Zdarzenie odwraca tę sytuację: ScoreKeeper ogłasza zmianę, a każdy zainteresowany subskrybuje zdarzenie. Znasz już event i Action z C#. W Unity wydawca i jego nasłuchujące komponenty to zwykle komponenty na różnych obiektach GameObject:

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, na tekście HUD
public ScoreKeeper keeper;
public TMP_Text label;

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

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

Action<int> oznacza, że każdy nasłuchujący to metoda przyjmująca jeden argument typu int — tutaj nowy wynik. Invoke wywołuje każdą subskrybowaną metodę w kolejności, w jakiej je subskrybowano. Jeśli nie ma nasłuchujących, zdarzenie ma wartość null, więc zwykłe OnScoreChanged(score) spowodowałoby wyjątek NullReferenceException, a ?. zamiast tego pomija wywołanie. Słowo kluczowe event ogranicza inne skrypty do używania += i -=: w ScoreLabel zapis keeper.OnScoreChanged(5) lub keeper.OnScoreChanged = null nie zostanie skompilowany.

ScoreKeeper nie ma pola dla etykiety i nie wie o jej istnieniu. Licznik kombinacji lub odtwarzacz dźwięku subskrybuje zdarzenie w ten sam sposób, a ScoreKeeper pozostaje bez zmian; scena testowa bez HUD działa bez błędów. Nasłuchujący odnajduje wydawcę za pomocą referencji z Inspektora, jak w tym przykładzie, albo w inny znany ci sposób, na przykład przez GetComponent lub singleton. Usunięcie nasłuchującego za pomocą -= ma znaczenie, gdy obiekty są niszczone — tym zajmiemy się w następnej lekcji.

challenge icon

Wyzwanie

Łatwy

Kombinacja ciosów wojownika rośnie przy każdym uderzeniu klawiszem Space i wraca do 0 po comboWindow (1) sekundzie bez uderzenia. Obecnie Fighter.cs sam ustawia tekst kombinacji i rozmiar płomienia, więc potrzebuje pola dla każdego z nich. Zmień to, używając zdarzenia:

  • W pliku Fighter.cs zadeklaruj publiczne zdarzenie o nazwie OnComboChanged, które przekazuje kombinację (int). Wywołuj je z nową wartością kombinacji za każdym razem, gdy ta się zmienia, również przy resecie do 0, i upewnij się, że uderzenie nie powoduje błędu, gdy nikt nie nasłuchuje.
  • Usuń pola comboText i flame z klasy Fighter oraz linie, które ich używają: Fighter nie wie nic o HUD.
  • W plikach ComboText.cs i ComboFlame.cs zasubskrybuj metody Show i Grow na zdarzenie wojownika w metodzie Start(). Oba skrypty mają pole fighter, połączone w scenie.

Naciśnij Play, uderz kilka razy w worek klawiszem Space, poczekaj sekundę, a następnie naciśnij Check.

Spróbuj swoich sił

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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Architektura gier w Unity