Menu
CoddyTech

Unity'de C# Olayları

Coddy'nin Unity Journey'sinin Unity'de Oyun Mimarisi bölümünün bir parçası. Ders 12 / 64.

Puan değiştiğinde birkaç şey bundan etkilenir: puan metni, bir ses, bir başarı. ScoreKeeper her birini çağırırsa, her biri için bir alana ihtiyaç duyar ve her yeni özellikte onu düzenlemek gerekir. Bir olay bu durumu tersine çevirir: ScoreKeeper değişikliği duyurur, ilgilenenler de abone olur.

Bunu sağlayan iki C# sözcüğü var. Action<int>, bir int alan ve hiçbir şey döndürmeyen bir metodun türüdür. Bu türden bir event, bu tür metotların listesidir: başka kodlar += ile kendi metodunu ekler ve sahibi hepsini Invoke ile çağırır. Sade C# ile:

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);
    }
}

// başka bir yerde
Alarm alarm = new Alarm();
Sleeper sleeper = new Sleeper();
alarm.Rang += sleeper.WakeUp;
alarm.Ring(7);   // 7'de uyandı

Unity'de yayıncı ve dinleyicileri, genellikle farklı GameObject'ler üzerinde bulunan bileşenlerdir:

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, HUD'nin metninde
public ScoreKeeper keeper;
public TMP_Text label;

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

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

Action<int>, her dinleyicinin bir int alan bir metot olduğu anlamına gelir; burada bu, yeni puandır. Invoke, abone olunan her metodu abone olma sırasına göre çağırır. Dinleyici yoksa olay null olur; bu nedenle doğrudan OnScoreChanged(score) çağrısı bir NullReferenceException hatası verir, oysa ?. çağrıyı atlar. event anahtar sözcüğü diğer betiklerin yalnızca += ve -= kullanmasına izin verir: ScoreLabel içinde keeper.OnScoreChanged(5) veya keeper.OnScoreChanged = null derlenmez.

ScoreKeeper'ın etiket için bir alanı yoktur ve etiketin varlığından haberdar değildir. Bir combo sayacı ya da ses çalar aynı şekilde abone olur ve ScoreKeeper olduğu gibi kalır; ayrıca HUD içermeyen bir test sahnesi hatasız çalışır. Bir dinleyici, buradaki gibi Inspector referansı üzerinden ya da GetComponent veya bir singleton gibi bildiğin herhangi bir yöntemle yayıncıyı bulur. Nesneler yok edilmeye başladığında -= ile dinleyiciyi kaldırmak önem kazanır; bu, sonraki derstir.

challenge icon

Görev

Kolay

Dövüşçünün kombosunu duyurmasını sağla.

  1. Fighter.cs dosyasına using System; ve public event Action<int> OnComboChanged; ekle.
  2. comboText ve flame kullanan satırları OnComboChanged?.Invoke(combo); ile değiştir ve her iki alanı da sil.
  3. ComboText ve ComboFlame sınıflarının Start() metodunda fighter.OnComboChanged += Show; ve += Grow; yaz.

“Oyna” düğmesine bas ve Space tuşuna birkaç kez bas: kombo büyür, ardından sıfırlanır. Sonra “Kontrol et” düğmesine bas.

Kendin dene

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;
            }
        }
    }
}

Unity'de Oyun Mimarisi bölümündeki tüm dersler

Kendi başına pratik yap: Unity playground