[WL-814g] 도트 모드 전환 MissingReferenceException(2): 이전 리그를 파괴 전에 비활성화 — Critter 의 FindAnyObjectByType 가 죽을 오브젝트를 잡던 문제 (#814)

PixelCameraManager.viewCamera/upscaledCanvas 는 [SerializeField] 가 아니라
프리팹에 저장되지 않아 인스턴스마다 항상 null → Initialize() 가 항상
FindAnyObjectByType 로 찾는다. Object.Destroy 는 프레임 끝 처리이므로
모드 전환(Teardown→Assemble 동일 프레임)에서 새 매니저가 아직 살아 있는
이전 리그의 뷰 카메라를 잡았고, 프레임 끝에 그것이 파괴되며
CanvasViewCamera.get_Aspect 에서 매 프레임 예외가 났다(PD 실측 200건).
FindAnyObjectByType 는 비활성 오브젝트를 제외하므로 파괴 전에 SetActive(false).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
깃 관리자 2026-09-12 17:33:19 +09:00
parent e519a52452
commit 36655c2ca7
1 changed files with 14 additions and 1 deletions

View File

@ -423,6 +423,17 @@ namespace WL.PixelArt
if (s_gameCam != null) s_gameCam.enabled = false; if (s_gameCam != null) s_gameCam.enabled = false;
if (s_viewCam != null) s_viewCam.enabled = false; if (s_viewCam != null) s_viewCam.enabled = false;
// 🔴 WL-814g — 그리고 리그를 **즉시 비활성**으로 내린다.
// Critter `PixelCameraManager.Initialize()`(PixelCameraManager.cs:123·132)는
// `viewCamera`/`upscaledCanvas` 를 **`FindAnyObjectByType` 로 찾는다**(두 필드는
// `[SerializeField]` 가 아니라 프리팹에 저장되지 않아 인스턴스마다 항상 null → 항상 Find).
// `Object.Destroy` 는 프레임 끝 처리라, 모드 전환에서 새 리그를 `Instantiate` 하는 순간
// **아직 살아 있는 이전 리그**의 뷰 카메라/캔버스를 새 매니저가 잡아 버리고,
// 프레임 끝에 그것들이 파괴되면서 `CanvasViewCamera.get_Aspect` 에서
// `MissingReferenceException` 이 매 프레임 터졌다(PD 실측 200건).
// `FindAnyObjectByType` 는 **비활성 오브젝트를 제외**하므로 여기서 내려두면 충돌이 사라진다.
if (s_rigRoot != null) s_rigRoot.SetActive(false);
// 원본 카메라 복원 — 스택에서 뷰 카메라부터 뺀다. // 원본 카메라 복원 — 스택에서 뷰 카메라부터 뺀다.
if (s_src != null) if (s_src != null)
{ {
@ -475,7 +486,9 @@ namespace WL.PixelArt
if (all[i] == null) continue; if (all[i] == null) continue;
var root = all[i].transform.parent != null ? all[i].transform.parent.gameObject : all[i].gameObject; var root = all[i].transform.parent != null ? all[i].transform.parent.gameObject : all[i].gameObject;
if (root == s_rigRoot) continue; if (root == s_rigRoot) continue;
if (root.name == RigName) DestroyObj(root); // 🔴 WL-814g — 파괴는 프레임 끝이라, 먼저 비활성으로 내려 새 리그의
// `FindAnyObjectByType` 가 이 잔재를 잡지 못하게 한다(위 Teardown 주석 참조).
if (root.name == RigName) { root.SetActive(false); DestroyObj(root); }
} }
// 프록시(원본 카메라의 자식)도 이름으로 정리 // 프록시(원본 카메라의 자식)도 이름으로 정리