빠른 흐름
[SerializeField] private Button startButton;
private void Awake()
{
startButton.onClick.AddListener(HandleStartClicked);
}기본 흐름
onClick 이벤트 등록 방식
Unity UI의 Button은 클릭 시 onClick 이벤트를 발생시킵니다. 인스펙터에서 직접 함수를 연결하는 방법도 있지만, 코드에서 AddListener로 등록하면 흐름을 한 곳에서 읽을 수 있어 유지보수가 편합니다. 팝업 열기, 씬 전환, 사운드 재생, 설정 저장 같은 UI 상호작용에서 기본처럼 쓰입니다.
OnEnable과 OnDisable에서 등록·해제하기
팝업처럼 여러 번 열고 닫히는 오브젝트에서는 OnEnable에서 리스너를 등록하고 OnDisable에서 해제하는 패턴이 안전합니다. Awake에서 한 번만 등록하면 중복 등록 위험은 없지만, 오브젝트 비활성화 주기가 있다면 OnEnable/OnDisable 쌍이 더 명확합니다.
using UnityEngine.UI;
[SerializeField] private Button closeButton;
[SerializeField] private GameObject panel;
private void OnEnable()
{
closeButton.onClick.AddListener(ClosePanel);
}
private void OnDisable()
{
closeButton.onClick.RemoveListener(ClosePanel);
}
private void ClosePanel()
{
panel.SetActive(false);
}인스펙터 연결과 코드 연결 비교
인스펙터에서 직접 함수를 연결하는 방식은 빠르게 설정할 수 있지만, 리팩터링 시 연결이 끊어지거나 참조 누락을 놓치기 쉽습니다. 코드에서 등록하면 컴파일 오류로 문제를 잡을 수 있어 규모가 커질수록 추적이 편합니다. 두 방식을 혼용하면 동일 이벤트가 두 번 실행될 수 있으므로 팀 내에서 일관된 방식을 정해 두는 편이 좋습니다.
체크포인트
| 상황 | 적합한 선택 |
|---|---|
| 간단한 버튼 연결, 빠른 프로토타이핑 | 인스펙터에서 직접 함수 연결 |
| 코드에서 흐름을 한 곳에서 관리 | onClick.AddListener(Method) |
| 여러 번 열고 닫히는 팝업 UI | OnEnable에서 등록, OnDisable에서 해제 |
| 한 번만 연결되는 UI (초기화 시) | Awake에서 AddListener |
| 연결 방식 | 더 잘 맞는 상황 | 주의할 점 |
|---|---|---|
| 인스펙터 직접 연결 | 버튼 수가 적고 디자이너가 바로 연결해야 할 때 | 리팩터링 후 누락을 컴파일로 못 잡음 |
메서드 AddListener | 흐름을 코드에서 추적하고 테스트하기 쉬워야 할 때 | 등록 위치와 해제 위치를 같이 관리해야 함 |
람다 AddListener(() => ...) | 일회성 전달 인자가 꼭 필요할 때 | 같은 람다를 RemoveListener로 빼기 어려움 |
주의할 점
OnEnable에서 등록하고 OnDisable에서 해제하지 않으면 팝업을 열 때마다 리스너가 중복 등록됩니다.
// ❌ 해제 없이 OnEnable에서만 등록 — 팝업 열 때마다 중복
private void OnEnable()
{
closeButton.onClick.AddListener(ClosePanel);
// ClosePanel이 여러 번 등록됨 → 클릭 시 여러 번 호출
}
// ✅ OnEnable/OnDisable 쌍으로 등록·해제
private void OnEnable()
{
closeButton.onClick.AddListener(ClosePanel);
}
private void OnDisable()
{
closeButton.onClick.RemoveListener(ClosePanel);
}
// ✅ 또는 Awake에서 한 번만 등록 (오브젝트 활성화 주기가 없는 경우)
private void Awake()
{
startButton.onClick.AddListener(HandleStart);
}반복 생성되는 버튼에 람다를 그대로 등록하면, 재사용 시 리스너 정리 지점이 흐려져 중복 실행되기 쉽습니다. 동적 버튼은 바인딩과 해제를 같은 수명주기에서 관리하세요.
// ❌ 풀링되는 버튼에 람다만 계속 추가
private void Bind(Button button, string sceneName)
{
button.onClick.AddListener(() => SceneManager.LoadScene(sceneName));
}
// 버튼을 재사용해도 기존 람다가 남아 중복 실행될 수 있음
// ✅ 바인딩 전에 기존 리스너를 정리하거나 명시적 메서드로 분리
private void Bind(Button button, string sceneName)
{
button.onClick.RemoveAllListeners();
button.onClick.AddListener(() => HandleSceneButton(sceneName));
}
private void HandleSceneButton(string sceneName)
{
SceneManager.LoadScene(sceneName);
}참고 링크
2 sources