원인은 재시작이 아니라 같은 실행 안의 Boot 씬 재로드다
DontDestroyOnLoad는 기존 객체를 다음 씬 로드에서 살려 둔다. 새로 읽은 씬에 같은 GameManager가 배치돼 있으면 그 복제본의 Awake도 실행된다. 프로세스를 완전히 종료했다가 다시 켜면 이전 런타임 객체는 사라지므로 이 글의 중복 원인과 다르다.
Unity 6000.5.3f1 빈 프로젝트에서 Boot→Game→Boot→Game→Boot를 돌리자 가드가 없는 GameManager 수는 다음 프레임마다 1→2→3으로 늘었다. 세 객체 모두 DontDestroyOnLoad 특수 씬에 있었고 첫 번째 Entity ID는 끝까지 그대로였다.
같은 Play 실행: Boot → Game → Boot → Game → Boot
가드 없음, 다음 프레임: 1 → 2 → 3
가드 적용, 다음 프레임: 1 → 1 → 1Awake에서 기존 생존자와 새 복제본을 가른다
GameManager는 씬의 루트 GameObject로 둔다. Unity 6.5 문서상 DontDestroyOnLoad는 루트 GameObject 또는 루트에 붙은 컴포넌트에만 쓸 수 있고, 루트를 보존하면 자식도 함께 넘어간다.
이 코드를 같은 순서로 다시 돌리자 Awake는 세 번 호출됐지만 새 복제본 두 개가 제거돼 다음 프레임 생존 수는 1→1→1이었다. 최초 생존자의 Entity ID도 바뀌지 않았다.
using UnityEngine;
public sealed class GameManager : MonoBehaviour
{
public static GameManager Instance { get; private set; }
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetStatics()
{
Instance = null;
}
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
private void OnDestroy()
{
if (Instance == this)
Instance = null;
}
}Destroy 직후에는 잠깐 두 개가 보일 수 있다
Destroy는 호출 줄에서 즉시 객체를 없애지 않고 현재 Update 루프 뒤에 처리한다. 재현에서도 중복 Awake 시점의 최대 생존 수는 2였고 다음 프레임에는 1로 돌아왔다. Awake 안에서 Destroy를 호출한 직후 개수를 세어 실패로 판정하지 말고 한 프레임 뒤에 확인한다.
Domain Reload OFF는 별개의 정적 상태 문제다
Boot 씬 재진입은 한 번의 Play 실행 안에서 새 씬 인스턴스가 생기는 문제다. Enter Play Mode Options에서 Domain Reload를 끄면 Play를 종료했다가 다시 시작할 때 정적 필드와 정적 이벤트가 남을 수 있는데, 이는 다른 경계다.
같은 Editor 프로세스에서 Play를 두 번 연속 실행해 이 경계도 따로 확인했다. 두 번째 Play의 SubsystemRegistration은 직전 세션의 Awake 3회와 복제 제거 2회를 읽은 뒤 정적 값을 초기화했다. 그래서 두 번째 세션의 Awake 카운트는 누적 6이 아니라 다시 3으로 끝났다. 두 Play 모두 가드 없음 1→2→3, 가드 적용 1→1→1이었다.
Boot 씬으로 되돌아가지 않는 구조도 중복 경로를 줄여 주지만, 씬 전환 실수 한 번에 매니저가 늘지 않도록 가드는 그대로 두는 편이 낫다.
직접 재현
검증일
검증 환경Unity 6000.5.3f1 (c2eb47b3a2a9), Windows 10 22H2, empty project, batchmode/nographics; default Domain Reload plus two consecutive Play sessions in one Editor process with Domain Reload disabled
Unity 6000.5.3f1 빈 프로젝트에서 Driver→Boot→Game→Boot→Game→Boot를 기본 Domain Reload로 1회, Domain Reload 비활성 상태의 같은 Editor 프로세스에서 Play 2회 연속 실행했다. 매회 가드 없음은 1→2→3, 가드 적용은 1→1→1이었다. 두 번째 Play 진입 때 SubsystemRegistration은 직전 Awake 3회·복제 제거 2회의 정적 값을 읽은 뒤 초기화했고, 현재 세션 카운트는 다시 3회부터 시작했다.