디버깅이란 항상 그렇듯 수시간 또는 수일을 고민해서 결국 해결봤더니 별 거 아니었더라.. 하는 경우가 많은데
이번에도 정말 어김없이, 그랬다. 두 번 겪고싶지는 않아서 기록해 둠.
이번 이슈의 개요는,
<MissingReferenceException>
Device Camera를 이용한 AR 프로젝트 빌딩 중, 여러 컨텐츠를 왔다갔다 실행하며 저 Exception Error을 띄웠다.
StackTracing을 해봤더니 전혀 엉뚱한 곳을 가리키고 있길래 아! 요고요고 그거다, eventHandler를 제대로 관리하지 않았구나, 하고 감이 왔었다.
<SceneLoad 관련 Action 추가함수>
간단한 디버깅 결과, 저 Action에서 null참조를 가리킨다는 것을 알았고(사실 여기까지 멍청하게 한시간 이상 걸림) 원인 파악에 나섰다.
+ 연산으로 Event Handler에 등록된 게임 오브젝트가 씬 전환 등으로 삭제가 되면
이 레퍼런스는 당연히 없는(null) 값을 가리키게 될 것이고, 그 값 또한 GC에 의해 null로 셋팅된다. 즉 헛손질을 하게 된다..는 것이었다.
그 후, 다시 + 연산이 호출될 때 null 값으로 정의된 레퍼런스는 그대로 유지된 채 Event가 붙어버려 Missing 오류를 띄우는 것.
객체를 두 개 이상 생성하는 것도 멍청했고, 이 Event의 참조 또한 객체 수만큼 늘어나는게 원초적인 문제라면 문제였다.
원래는 위 주석처리된 함수처럼 람다식을 이용해 event를 붙였지만, 객체가 생성과 파괴를 반복할 수도 있다는 것을 알았으니
함수형으로 만들고, 해당 객체가 파괴되기 전에 Action을 빼 주는 코드를 추가했다.
<자, 이제 빼 주자.>
객체가(여기서는 AR관련 스크립트를 포함한 객체) 비활성화 될때 해당 Action을 빼 준다. 해결!! 하면서 다시 테스트를 해 보았지만..
안된다.(2차빡침)
왜? 대체 왜? 분명히 Event까지 잘 빼주고, 객체가 다중생성 되는것, 그리고 GC와 Resource관련 패널도 정확히 검사했는데 대체 왜..?
그리고 이 버그가 특정 Scene의 이동시에만 발생하는 버그가 StackTracing을 더 어렵게 만들었다.
아무리 생각해도 이 Action에서 문제를 일으키는건 응당해보여서 다시 Test를 해봤더니..
OnDisable()이 호출 자체가 안 된다.
-_-?? 그럴 수 있나?
코드를 보면 알겠지만 해당 액션은 SceneManager의 sceneLoaded에 관한 것이다. 하지만 해당 스크립트를 사용하는 씬은 Additive모드로 가져온 것.
<해당 Scene의 Hierarchy 구조>
현재 ARCamera Scene이 Additive 모드로 불려져 있고, 여기서 네트워크 신호(Exit Response)를 받으면 다른 Scene이 AsyncLoad가 되는 구조였다.
즉, 본디 실행중인 메인 Scene에서 비동기 씬로드가 이루어지면 Additive Scene에 포함된 객체에서 OnDisable()이 호출이 되지 않는다는 것.
호오.......
응, 그래서 어떻게든 객체가 파괴되는 시점은 분명히 올 것이라 생각하고 OnDestroy에 넣었더니
정상적으로 Event를 잘 빼주게 되더라. 여기서 1차 환호. 디버깅은 완료했다.
사실 Event Handler에 등록한 그 Action은 단순히 Device Camera를 찾아 셋팅하는 기능 밖엔 없었다 ^ u^;; 결국 1회용 함수라 생각해서
카메라를 끌 때 빼는것도, 파괴될때 빼는것도 아닌 그냥.. 그냥 넣자마자 빼면 단순히 해결이 되는 문제였다 - _-;
'Works > Programming' 카테고리의 다른 글
Jarray.Clear() 메소드의 참조스택 (0) | 2021.02.17 |
---|---|
Dobby is Free! (출퇴근 타이머) v3.1 (1) | 2020.08.05 |
유니티 빌드오류 : Failed to align APK (0) | 2019.09.17 |
.db, .bytes, .xml, .sql, .csv 자유로이 왔다갔다하기 (0) | 2019.09.09 |
마비노기 염색 도우미 수정 (0) | 2018.09.27 |