본문 바로가기

무제_LR

ScriptableObject로 전역 이벤트 써먹기

디버그 메뉴를 만들어보고자 ScriptableObject Event를 써봤습니다.

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Localization;

[CreateAssetMenu(fileName = "ScriptableEventSO", menuName = "SO/ScriptableEvent")]
public class ScriptableEventSO : ScriptableObject
{
//외부에서 Register받은 Listener(아래 있음)들을 저장
  private List<ScriptableLocaleEventListener> setLocaleListeners = new ();

//호출 시 관련 리스너들 호출
  public void OnLocaleChanged(Locale locale)
  {
    for (int i = 0; i < setLocaleListeners.Count; i++)
      setLocaleListeners[i].Raise(locale);
  }

  public void RegisterSetLocaleEvent(ScriptableLocaleEventListener listener)
    => setLocaleListeners.Add(listener);

  public void UnregisterSetLocaleEvent(ScriptableLocaleEventListener listener)
    => setLocaleListeners.Remove(listener);
}
//컴포넌트로 부착할 리스너
public class ScriptableLocaleEventListener : MonoBehaviour
{
//이벤트 타입같은건 적당히 수정해서 사용하기
  public enum LocaleEventType
  {
    SetLocale,
  }

  [SerializeField] private ScriptableEventSO so;
  [SerializeField] private LocaleEventType type;
  [SerializeField] private UnityEvent<Locale> setLocaleEvent;

//OnEnable에서 SO에 자기 자신을 자동으로 등록
  private void OnEnable()
  {
    switch (type)
    {
      case LocaleEventType.SetLocale:
        so.RegisterSetLocaleEvent(this);
        break;

      default: throw new System.NotImplementedException();
    }
  }

//꺼질 때는 등록 해제
  private void OnDisable()
  {
    switch (type)
    {
      case LocaleEventType.SetLocale:
        so.RegisterSetLocaleEvent(this);
        break;

      default: throw new System.NotImplementedException();
    }
  }

//Raise 호출로 사전에 설정된 이벤트 호출
  public void Raise(Locale locale)
    => setLocaleEvent?.Invoke(locale);
}

 

적당히 캔버스와 UI를 생성해주고 DebuggingUI를 붙였습니다.

public class DebuggingUI : MonoBehaviour
{
  [SerializeField] private KeyCode enableKeyCode = KeyCode.F1;
  [SerializeField] private GameObject root;
  [SerializeField] private ScriptableEventSO scriptableEventSO;

  private void Update()
  {
    if (Input.GetKeyDown(enableKeyCode))
      root.SetActive(!root.activeInHierarchy);
  }

  public void OnLocaleButtonClicked(Locale locale)
    => scriptableEventSO.OnLocaleChanged(locale);
}

일단 SO를 통한 전역 이벤트 호출이 먹히는지 테스트를 위해 Locale 설정용 버튼들을 추가했습니다.

이제 이 버튼이 입력된다면 DebuggingUI.OnLocaleButtonClicked -> ScriptableEventSO.OnLocaleChanged가 호출되어 SO에 등록된 Listener들이 활성화 신호를 받겠네요.

현명한 독자분들은 아직 Listener 컴포넌트를 못 보셨다는 것을 눈치채셨을 것입니다.

어짜피 아래 스크린샷 나올테지만 공백이 좀 허해 보여서 끄적여봤습니다.

PlayMode에 들어가면 이 Listener가 OnEnable에서 자기 자신을 인스펙터의 ScriptableEventSO에 Register할 테고,

SO가 호출할 때마다 하단에 설정된 이벤트를 호출하겠네요.

 

 

햅삐햅삐햅삐~