턴제 카드 게임을 만들다보니 많은 곳에서 이벤트를 사용합니다.

스킬 효과, 장비 효과, 유물 등과 같이 전투 내에서만 필요한 것들(전투 스테이지가 끝나면 -=로 해제되어야 하는)

(스킬은 전투 시작시 구독, 스킬 삭제 시 구독해제. 장비는 착용 시 구독, 착용 해제 시 구독 해제. 유물은 런동안 영구 지속, 이 외의 효과도 생명주기가 각각 다릅니다)

그리고 해금시스템과 같이 게임 플레이 내내 이벤트를 구독해야하는 것들(게임 시작 직후 한번만 +=하면 되는)

이렇게 2가지로 볼 수 있을 거 같습니다.


모든 이벤트들을 static Events 클래스에서 관리하고 있습니다.


public static class Events{
    public static Action<DamageInfo> OnTakeDamage;
    //이런게 매우 많음!
    
    public static void Registr<T>(ref Action<T> evt, Action<T> fun, object caller) {
        evt += fun;
#if UNITY_EDITOR
        Debug.Log($"[Events] Registr {evt.Method.Name} from {caller?.GetType().Name}");
#endif
    }
 
    public static void Trigger<T>(Action<T> evt, T args, object caller) {
        evt?.Invoke(args);
#if UNITY_EDITOR
        Debug.Log($"[Events] Trigger {evt.Method.Name} from {caller?.GetType().Name}");
#endif
    }

    public static void UnSubscribe<T>(ref Action<T> evt, Action<T> funobject caller) {
        evt -= fun;
#if UNITY_EDITOR
        Debug.Log($"[Events] Trigger {evt.Method.Name} from {caller?.GetType().Name}");
#endif
    }
}





지금 제가 생각하는 고민은 전투 내에서 쓰이게 될 효과 컴포넌트들이 워낙 많은데 이 모든 효과들에 대해, 그리고 특정 타이밍(Dead, OnDisable, OnAble, Equip, UnEquip 등...)에,

하나하나

Events.Registr(Events.OnTakeDamage, GoodFunction, this);

Events.UnSubscribe(Events.OnTakeDamage, GoodFunction, this);

를 호출하는 것이 최선의 방법일까요?

뭔가 실수로 구독 해제 구문을 빼먹어서 누수가 생기거나 여러 전투 스테이지를 반복하면서 같은 이벤트가 여러번 구독되어 버리는 사고가 나지 않을까 하는 괜한 걱정이 들어서요.


나름 챗지피티한테 계속 대가리를 박아보고 생각했을때 몇가지 방법이 더 있었습니다.

1. 이런 류의 모든 객체를 IEventEffect로 묶고 매니저에서 전투가 시작하고 끝날때 IEventEffect를 전부 수집한다음 Registr와 UnSubscribe를 호출하면 된다는데 아직도 이게 최선일까? 하는 생각이 드네요.


2. 1번 방법에서 더 나아가 List<IEventEffect> runEvents; List<IEventEffect> battleEvents; 이런식으로 나눈 후 전투가 끝나면 battleEvents에 대해서만 UnSubscribe를 하는 겁니다.


3. 다음과 같습니다.

public static void Registr<T>(ref Action<T> evt, ref Action<T> function)
{
    subs.Add(() => evt -= function);
}
 
public static void UnSubsAll(){
    foreach(var sub in subs){
        sub.Invoke();
    }
}

이런 구조를 생각했었는데 챗지피티가 'ref 파라미터는 람다 또는 클로저 내에서 사용할 수 없습니다.'라고 불가능하다네요.


4. 그래서 생각한 방법이 리플렉션으로 string 값을 통해 이벤트를 찾아오는 건데 이것도 지피티씨가 비용이 비싸서 전투 중 수많은 효과에 쓰기엔 무리가 있을거라고 합니다.


그래서 계속 고민하다 고수님들께 묻는게 빠를 거 같아 글을 써봅니다.

앞서말한 실수가 안생길 수 있도록 설계 방식이 있을까요? 고수님들은 이벤트를 어떻게 관리하는지도 궁금합니다.

글 읽어주셔서 감사합니다.