본문 바로가기

Unity/정보

[Unity 유니티] 람다식 AddListener for문 안됨 - 클로저 (Closure) 문제

AddListener는 Unity에서 UI 버튼이나 기타 이벤트가 발생할 때 특정 함수를 호출하기 위해 주로 사용하는 기능이다. 하지만 AddListener를 반복문, 특히 for문과 함께 사용할 때는 주의해야 한다. 잘못 사용할 경우 의도치 않은 결과를 초래할 수 있기 때문이다.


문제점: 클로저(Closure)와 캡처링(Capturing)의 혼란

for문을 통해 AddListener를 반복해서 호출할 때, 각 반복마다 AddListener가 현재의 루프 변수를 '캡처'하는데, 이로 인해 예상치 못한 버그가 발생할 수 있다. 이는 C#의 람다식이 클로저를 통해 외부 변수를 캡처하는 방식 때문이다.

예를 들어, 아래와 같은 코드가 있다고 가정하자

void Start()
{
    for (int i = 0; i < 5; i++)
    {
        button.onClick.AddListener(() => Debug.Log(i));
    }
}

위 코드에서 의도한 대로 각 버튼 클릭 시 0, 1, 2, 3, 4가 출력될 것 같지만, 실제로는 5가 반복 출력된다. 이는 i의 값을 AddListener가 캡처할 때 마지막 값이 5로 고정되기 때문이다.

해결 방법: 임시 변수 사용

이 문제를 해결하려면 for문 안에서 임시 변수를 만들어야 한다. 아래와 같이 작성하면 된다

void Start()
{
    for (int i = 0; i < 5; i++)
    {
        int temp = i; // 임시 변수 생성
        button.onClick.AddListener(() => Debug.Log(temp));
    }
}

이제 각 버튼 클릭 시 temp의 현재 값이 캡처되므로 의도한 대로 0, 1, 2, 3, 4가 출력된다.


결론

AddListener와 같은 이벤트 핸들러를 사용할 때는 반복문 안에서 직접 루프 변수를 참조하지 말고, 임시 변수를 통해 값을 캡처하도록 해야 한다. 이는 Unity뿐 아니라 C#의 람다와 클로저를 사용하는 모든 코드에서 중요한 습관이다.