내일배움캠프

내일배움캠프: for문을 통한 AddListener 등록 시 인자 전달 문제 해결 방법

pracumj 2024. 11. 7. 21:33

 

문제 상황

Unity에서 for문을 통해 UI 버튼에 이벤트 리스너를 등록하던 중 내가 생각한 값이 아니라 이상한 값이 들어가는 현상이 생

겼다. 코드상에서 원인을 찾을 수 없어서 중단점을 통해 확인해보니 메서드에 전달해준 인자 값이 계속 증가한다는 것을 확인 했다. 

해당 문제를 해결하기위해 구글링을 통해서 자료를 찾아보니 람다식은 인자를 참조 해서 그 문제가 생긴다는 것을 알았다. 

 

문제 코드 

for (int i = 0; i < 10; i++)
{
    button.onClick.AddListener(() => SomeMethod(i));
}

AddListenr를 통해 인자 값을 넘겨줄 때는 람다식 혹은 델리게이트를 사용해 넘겨줘야하는데 람다식과 델리게이트 모두 

참조형으로 값을 가지고 있기 때문에 문제가 발생했다. 

해결 코드

for (int i = 0; i < 10; i++)
{
    int index = i;  
    button.onClick.AddListener(() => SomeMethod(index));
}

 

문제의 원인은 람다식이나 델리게이트가 i값을 참조하고 있는데, for문에서 i 값이 계속 변경되기 때문이었다. 클릭 이벤트는  for문 반복이 완료된 후 발생하기 때문에 모두 동일한 i값을 참조하고 있던 것 이다. 

해결 방법은 의외로 간단했다.  i값을 바로 람다식에 넣어주는 것이 아니라 값 형의 지역 변수에 넣고 이를 람다식에 넣어주는 것이었다. 선언된 index 지역 변수는 값 형이기 때문에 한 번 설정된 값은 변경되지 않는다. 따라서 람다식이나 델리게이트가 index를 참조할 때, 고정된 값을 참조하게 되므로 원하는 i 값을  전달할 수 있게 됐다.

  

마무리

for문을 통해 이벤트 리스너를 등록할 때 인자 값이 동일해지는 이유는 람다식이나 델리게이트가 변수 i를 참조 형태로 저장하기 때문이었다. 이를 방지하기 위해서는 for문 내부에서 새로운 값형 지역 변수를 선언하여 고정된 값을 참조하도록 코드를 수정하면 된다.