うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】UnityEvent に関して

Button 等 uGUI の要素には 押されたときなどのイベントをハンドルするために UnityEvent が利用されています


UnityEvent にはイベントを登録する方法として下記の2つの方法がある

  1. Inspector から GameObject と メソッドを指定
    f:id:hacchi_man:20200613210630p:plain:w200

  2. Script から イベントを登録

   private void Start()
    {
        _button.onClick.AddListener(Click);
    }

    public void Click(){}

がしかし、Script を書く側としては 1 の方法を利用してくしくない

Inspector からメソッドを指定する際の問題 [1]

呼び出すメソッド名が変更されると再度登録し直す必要があり
IDE を利用している際に呼び出し元が探せないので、利用されているかされてないのか分からなくなる
f:id:hacchi_man:20200613211136p:plain

Inspector からメソッドを指定する際の問題 [2]

RemoveAllListeners を呼び出しても削除されない

UnityEvent には登録したイベントを削除するメソッドとして RemoveAllListener が用意されていますが
こちらは Inspector から登録したイベントを削除できません

    /// <summary>
    ///   <para>Remove all non-persisent (ie created from script) listeners  from the event.</para>
    /// </summary>
    public void RemoveAllListeners()
    {
      this.m_Calls.Clear();
    }

それもそのはずで RemoveAllListeners で削除するのは m_Calls に登録されているイベントのみで
Inspector からは m_PersistentCalls に登録されるためです

public abstract class UnityEventBase : ISerializationCallbackReceiver
  {
    private bool m_CallsDirty = true;
    private InvokableCallList m_Calls;
    [FormerlySerializedAs("m_PersistentListeners")]
    [SerializeField]
    private PersistentCallGroup m_PersistentCalls;
}

これに関しては公式にも 非永続的 と記述されているので、確認すればわかるものですが・・・
f:id:hacchi_man:20200613213057p:plain

もし 永続的なイベントの管理をする場合 UnityEventBase.SetPersistentListenerState から実行しないようにはできそうです