Unity - Delegates ve Events Kullanımı

Unity - Delegates ve Events Kullanımı

2023-01-31    

Delegeler (delegate) ve olaylar (event) C# dilinin vazgeçilmez birer parçası olduğunu biliyoruz. Unity tarafında çok kullanılan bu yöntemleri inceleyeceğiz.

Unity Delegate ve Event Kullanımı

Bu yazıda, delegeleri ve bunların olay sistemi oluşturmak için nasıl kullanılabileceğini göreceğiz. Delegeler, bazı olaylar(event) meydana geldiğinde dinleyicilerin (listeners) mesajlarını yayınlamak için kullanılan yöntemleri (method) ve olayları(event) saklar.

Delegates

Delegeler, metodlara başvurmak için kullanılan veri türüdür. Delegeler oluşturulurken parametreleri ve dönüş tipi tanımlanmalıdır. İmzalar eşleştiği sürece herhangi bir yöntemi tutabilir.

Nesnelere benzer şekilde, delegeler her yerden aktarılabilir ve kullanılabilir.

Events

Olaylar, bir şey olduğunda dinleyicilere mesaj yayınlamak için kullanılır. Bir olay sistemi iki varlıktan oluşur: bir dinleyici (listener) ve bir yayıcı (emitter). Bir yayıcı tarafından çağrılan bir olayı dinleyen birden çok dinleyici olabilir.

Olaylar, diğer ayrıntıları bilmeden sadece bir şeyin ne zaman olduğunu bilmek istediğimiz durumlar için yararlı olabilir. Dinleyiciler bağımsızdır, dolayısıyla bir dinleyici bir olay tetiklendiğinde diğer dinleyicilerin ne yaptığıyla ilgilenmemelidir.

Burada oyuncunun sağlığı ve aldığı hasarlar sonrası diğer bileşenlerin haberdar edilmesi üzerine kurulu basit bir kurgu gösterilmiştir.

using UnityEngine;

[CreateAssetMenu(fileName = "Health", menuName = "Health", order = 0)]
public class Health : ScriptableObject
{
    public delegate void DamageTaken(float damage);

    public event DamageTaken OnDamageTaken;

    public delegate void PlayerDead();

    public event PlayerDead OnDead;

    [SerializedField]
    private float health = 100;

    public void TakeDamage(float damage)
    {
        if (health <= 0) return;

        health -= 20;
        if (OnDamageTaken != null)
        {
            OnDamageTaken.Invoke (damage);
        }

        if (health <= 0)
        {
            if (OnDead != null)
            {
                OnDead.Invoke();
            }
        }
    }
}

Yukarıda oyuncunun sağlığı tutan ve hasar aldıkça sağlığı güncelleyen bir nesnemiz var. Bu nesne içerisinde delegeler vasıtasıyla olaylar saklanır. Bu olayları dinleyen diğer nesneler oyuncu sağlığı değiştikçe haberdar edilir.

using UnityEngine;

public class DeathUI : MonoBehaviour
{
    [SerializedField]
    private Health playerHealth;

    private void Awake()
    {
        playerHealth.OnDead += OnDeath;
    }

    private void OnDeath()
    {
        Debug.Log("You Died");
    }
}
using UnityEngine;

public class DamageUI : MonoBehaviour
{
    [SerializedField]
    private Health playerHealth;

    private void Awake()
    {
        playerHealth.OnDead += PlayerDied;
        playerHealth.OnDamageTaken += DamageTaken;
    }

    private void DamageTaken(float damage)
    {
        Debug.Log($"Player takes {damage} damage");
    }

    private void PlayerDied()
    {
        Debug.Log("Show dead effect");
    }
}

Yukarıda iki farklı UI bileşeni oyuncu sağlığını dinlemesi kurgulanmıştır.

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private Health health;

    private void Awake()
    {
        health = GetComponent<Health>();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            health.TakeDamage(20);
        }
    }
}

Yukarıda oyuncu denetleyicimiz oyuncu nesnesine eklenmiş Health (Scriptable Object) bileşenini her güncellemede hasar oluşturarak olayı tetikler. Tetiklenen olay dinleyiciler tarafından algılanır ve ilgili görsel güncellemeler (ekrandaki sağlık barı veya ölüm olunca oyunun durudurulması gibi) yapılır.