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.
Wyzwanie
ŁatwyKombinacja 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.cszadeklaruj publiczne zdarzenie o nazwieOnComboChanged, 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
comboTextiflamez klasy Fighter oraz linie, które ich używają: Fighter nie wie nic o HUD. - W plikach
ComboText.csiComboFlame.cszasubskrybuj metodyShowiGrowna zdarzenie wojownika w metodzieStart(). Oba skrypty mają polefighter, 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;
}
}
}
}
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
1Komponenty, nie hierarchie
Małe komponentyPodstawowy skrypt przeciwnikaKomponenty abstrakcyjneWspółpracujące komponentyPodsumowanie: modułowa wieżyczka4Dane serializowane
Klasy serializowalneListy w InspectorzeWyliczenia w InspectorzePodsumowanie: tabela łupów10Projekt: Arena przetrwania
BohaterTypy wrogów2Interfejsy w Unity
IDamageableInterfejsy i TryGetComponentGetComponentsPodsumowanie: klawisz interakcji5ScriptableObjects
Zasoby danychStatystyki broniWspółdzielone ustawieniaFale jako danePowtórka: baza danych przedmiotów8Kod wielokrotnego użytku
Metody rozszerzająceGeneryczny singletonGeneryczne metody pomocniczePodsumowanie: FindNearest3Zdarzenia
Zdarzenia C# w UnitySubskrypcja w OnEnablePola UnityEventZdarzenia sterują interfejsemPodsumowanie: wyskakujące okno osiągnięcia6Zapisywanie za pomocą JSON
JsonUtilityZapisz gręWczytywanie i wartości domyślnePowtórka: sloty zapisu