[Unity] Button OnClick Event triggered twice

유니티에서 버튼 UI를 쓰면 OnClick 이벤트에 메서드를 할당하여 사용하게 된다.

 

메서드는 보통 인스펙터 창에서 추가하거나, 혹은 스크립트에서 button.onClick.AddListener()를 사용하여 넣어준다.

 

인스펙터 창 OnClick

using System;
using UnityEngine;
using UnityEngine.UI;

public class TestButton: MonoBehaviour
{
    Button button;
    void Awake()
    {
        button = GetComponent<Button>();
        button.onClick.AddListener(OnClickButton);
    }
    
    void OnClickButton()
    {
    	Debug.Log($"Button clicked");
    }
}

 

그런데 C# 스크립트로 메서드를 할당하면, 버튼을 클릭했을 때 버튼에 할당된 메서드가 두 번 실행되는 문제가 발생한다.

 

1. Input Setting

구글에 검색했을 때 처음 나온 해결책은 InputSetting을 바꾸는 것이었다.

https://discussions.unity.com/t/button-onclick-event-is-firing-twice/600697

 

하지만 나의 경우 Input Setting은 문제가 없어서 도움은 되지 않았다.

 

2. Remove All Listener

이후에 검색했을 때 나온 방법으로, AddListener를 하기 전에 RemoveAllListener를 통해 메서드를 다 지워준다.

https://stackoverflow.com/questions/64338261/button-onclick-listener-triggers-twice

아마 이유는 한 번 함수가 추가되고 나서, 게임을 껐을 때 함수가 남아있어 두 번 실행되는 것으로 보인다.

 

애초에 이런 일이 발생하지 않도록 OnDestroy나 OnDisable에서 RemoveAllListener를 해주는 것이 나아보인다.

using System;
using UnityEngine;
using UnityEngine.UI;

public class TestButton : MonoBehaviour
{
    Button button;
    void Awake()
    {
        button = GetComponent<Button>();
        // AddListener 이전에 등록된 모든 메서드 제거
        //button.onClick.RemoveAllListeners();
        button.onClick.AddListener(OnClickButton);
    }

    void OnClickButton()
    {
        Debug.Log($"Button clicked");
    }

    void OnDisable()
    {
        button.onClick.RemoveAllListeners();
    }

    void OnDestroy()
    {
        button.onClick.RemoveAllListeners();
    }
}

 

3. With UnityAction

만약 onClick에 UnityAction을 만들어 넣었다면, UnityAction도 마찬가지로 등록된 함수들을 없애줘야 한다.

using System;
using UnityEngine;
using UnityEngine.UI;

public class TestButton : MonoBehaviour
{
    Button button;
    UnityAction buttonEvent;
    void Awake()
    {
        button = GetComponent<Button>();
        buttonEvent += OnClickButton;
        button.onClick.AddListener(buttonEvent);
    }

    void OnClickButton()
    {
        Debug.Log($"Button clicked");
    }

    void OnDisable()
    {
        buttonEvent -= OnClickButton;
        button.onClick.RemoveAllListeners();
    }

    void OnDestroy()
    {
        buttonEvent -= OnClickButton;
        button.onClick.RemoveAllListeners();
    }
}