| WeakReference를 사용해서 구독자가 파괴되면 자동으로 GC가 수거 되는 EventBus를 만들어
보겠습니다. 구독자(this), 메서드를 묶어서 관리 합니다. Publish시 살아있는 구독자만 호출 합니다. 1. EventBus 구현 SafeEventBus.cs 파일 using System;
using System.Collections.Generic; using UnityEngine; public static class SafeEventBus { private class Subscription { public WeakReference TargetRef; // 구독자 객체 (MonoBehaviour) public Delegate Callback; // Action<T> } private static readonly Dictionary<Type, List<Subscription>> events = new(); public static void Subscribe<T>(MonoBehaviour subscriber, Action<T> callback) { if (subscriber == null || callback == null) throw new ArgumentNullException(); var type = typeof(T); if (!events.TryGetValue(type, out var list)) { list = new List<Subscription>(); events[type] = list; } list.Add(new Subscription { TargetRef = new WeakReference(subscriber), Callback = callback }); } // 이벤트 발행 public static void Publish<T>(T evt) { var type = typeof(T); if (!events.TryGetValue(type, out var list)) return; // 살아있는 구독자만 호출 for (int i = list.Count - 1; i >= 0; i--) { var sub = list[i]; if (sub.TargetRef.IsAlive) { ((Action<T>)sub.Callback)?.Invoke(evt); } else { // 이미 파괴된 구독자는 제거 list.RemoveAt(i); } } // 리스트가 비었으면 타입 제거 if (list.Count == 0) events.Remove(type); } // 명시적 해제 (선택) public static void Unsubscribe<T>(MonoBehaviour subscriber, Action<T> callback) { if (subscriber == null || callback == null) return; var type = typeof(T); if (!events.TryGetValue(type, out var list)) return; list.RemoveAll(sub => (object)sub.TargetRef.Target == subscriber && sub.Callback == (Delegate)callback); if (list.Count == 0) events.Remove(type); } } 2. Event 정의 PlayerScoreEvent.cs 파일 public class PlayerScoredEvent
{ public int Score { get; private set; } public PlayerScoredEvent(int score) { Score = score; } } 3. 이벤트 구독 ScoreManager.cs 파일 using UnityEngine;
public class ScoreManager : MonoBehaviour { void OnEnable() { SafeEventBus.Subscribe<PlayerScoredEvent>(this, OnPlayerScored); } void OnDisable() { SafeEventBus.Unsubscribe<PlayerScoredEvent>(this,OnPlayerScored); } void OnPlayerScored(PlayerScoredEvent e) { Debug.Log("SafeEventBus: Score: " + e.Score); } } 4. 이벤트 발행 EventBus.Publish(new PlayerScoredEvent(10));
✅ 특징:
|