Zdarzenia C# w Unity
Część sekcji Architektura gier w Unity ścieżki Unity w Coddy. Lekcja 12 z 64.
Gdy wynik się zmienia, interesuje to kilka elementów: tekst wyniku, dźwięk, osiągnięcie. Jeśli ScoreKeeper wywołuje każdy z nich, potrzebuje pola dla każdego, a każda nowa funkcja oznacza konieczność edycji tej klasy. Zdarzenie odwraca tę sytuację: ScoreKeeper ogłasza zmianę, a zainteresowani subskrybują zdarzenie.
Dwa słowa C# sprawiają, że to działa. Action<int> to typ metody, która przyjmuje jeden int i niczego nie zwraca. event tego typu to lista takich metod: inny kod dodaje swoją metodę za pomocą +=, a właściciel wywołuje je wszystkie przez Invoke. W zwykłym C#:
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);
}
}
// w innym miejscu
Alarm alarm = new Alarm();
Sleeper sleeper = new Sleeper();
alarm.Rang += sleeper.WakeUp;
alarm.Ring(7); // Pobudka o 7W Unity nadawca i jego odbiorcy to komponenty, zwykle umieszczone 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 odbiorca to metoda przyjmująca jeden int — tutaj nowy wynik. Invoke wywołuje każdą subskrybowaną metodę w kolejności, w jakiej się zasubskrybowały. Gdy nie ma żadnego odbiorcy, 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. Odbiorca odnajduje nadawcę za pomocą referencji z Inspektora, jak w tym przykładzie, albo w dowolny znany Ci sposób, na przykład przez GetComponent lub singleton. Usunięcie odbiorcy za pomocą -= ma znaczenie, gdy obiekty są niszczone — to temat następnej lekcji.
Wyzwanie
ŁatwySpraw, by wojownik ogłaszał swoją serię.
- W pliku
Fighter.csdodajusing System;ipublic event Action<int> OnComboChanged;. - Zastąp linie używające
comboTextiflamekodemOnComboChanged?.Invoke(combo);i usuń oba pola. - W metodzie
Start()w klasachComboTextiComboFlamewpiszfighter.OnComboChanged += Show;i+= Grow;.
Naciśnij „Graj” i naciśnij kilka razy spację: seria rośnie, a potem się zeruje. Następnie naciśnij „Sprawdź”.
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;
}
}
}
}
Wszystkie lekcje w sekcji Architektura gier w Unity
1Komponenty, nie hierarchie
Małe komponentyBazowy skrypt przeciwnikaKomponenty abstrakcyjneWspółpracujące komponentyPowtórka: modułowa wieżyczkaPowtórka: podwójne działo4Dane serializowane
Klasy serializowalneListy w InspectorzeEnumy w InspectorzePodsumowanie: tabela łupówPodsumowanie: losowanie łupów2Interfejsy w Unity
IDamageableInterfejsy i TryGetComponentGetComponentsPowtórka: klawisz interakcjiPowtórka: najbliższy w zasięgu5ScriptableObjects
Zasoby danychStatystyki broniWspółdzielone ustawieniaOcal wiatrFale jako danePowtórka: Baza przedmiotówPowtórka: Kupowanie w sklepie8Kod wielokrotnego użytku
Metody rozszerzająceGeneryczny singletonGeneryczne metody pomocniczePodsumowanie: FindNearest3Zdarzenia
Zdarzenia C# w UnitySubskrybuj w OnEnablePola UnityEventZdarzenia sterują UIPodsumowanie: popup osiągnięciaPodsumowanie: timer popupu6Zapisywanie za pomocą JSON
JsonUtilityZapisz gręWczytywanie i wartości domyślnePodsumowanie: sloty zapisuWybierz i usuń slotPoćwicz samodzielnie: Edytor online Unity