[TIL] Destroy 메서드의 진실
📖학습 내용
유니티 개발 학습 및 트러블슈팅 정리
싱글톤 중복 생성 시 Destroy와 Start() 실행 순서 문제 해결
문제 상황: - 싱글톤 오브젝트의 Awake()에서 중복 인스턴스를 Destroy(gameObject)로 파괴 예약해도, 실제 파괴는 프레임 후반에 일어나므로 해당 중복 인스턴스의 Start() 메서드가 실행되어 이벤트 구독 등 불필요한 초기화 작업 후 NullReferenceException을 유발함
해결 방법:
- **`OnDestroy()`에서 이벤트 해제:**
private void Start()
{
playerResource = PlayerController.Instance.GetComponent<PlayerResource>();
if(playerResource != null )
{
playerResource.OnGoldChanged += UpdateUI;
UpdateUI();
}
}
private void OnDestroy()
{
playerResource.OnGoldChanged -= UpdateUI;
}
추가 가능 해결책:
DestroyImmediate(): 즉시 파괴하지만 런타임 도중 사용은 예기치 않은 오류 가능성으로 비권장됨.- 중복 인스턴스 플래그 사용:
Awake()에서 중복 인스턴스 감지 시,bool isDuplicate = true;와 같은 플래그를 설정하고Destroy(gameObject);호출 후 즉시return;함. - 생명주기 메서드 실행 차단:
Start(),OnEnable(),Update()등 주요 생명주기 메서드 시작 부분에if (isDuplicate) return;구문을 추가하여, 파괴될 예정인 중복 인스턴스가 어떠한 로직도 실행하지 않도록 원천 차단.
PlayOneShot 사운드 미재생 문제 (아이템 즉시 파괴 시)
문제 상황:
AudioSource.PlayOneShot()호출 직후 해당AudioSource를 가진 게임 오브젝트가Destroy()되면, 소리가 재생될 충분한 시간을 갖지 못하고 끊기거나 재생되지 않음.
해결 방법: - AudioSource.PlayClipAtPoint(AudioClip clip, Vector3 position, float volume): 가장 간단한 방법. 지정된 위치에 임시 게임 오브젝트와 AudioSource를 생성하여 클립을 재생하고, 재생이 끝나면 자동으로 임시 오브젝트를 파괴.
public void PlaySoundEffect()
{
if (audioClip != null)
{
AudioSource.PlayClipAtPoint(audioClip,transform.position, 1.0f);
}
}
추가 가능 해결책:
- 사운드 매니저 (AudioManager): 싱글톤 패턴의 사운드 매니저에게 사운드 재생을 요청하는 방식. 사운드 매니저가 실제 재생을 담당하므로 더 체계적인 사운드 관리가 가능.
- 시각/물리적 요소만 즉시 제거 후 지연 파괴: 아이템의
Renderer와Collider를 먼저 비활성화하여 플레이어에게는 즉시 사라진 것처럼 보이게 하고,AudioSource.PlayOneShot()으로 소리를 재생한 뒤Destroy(gameObject, clip.length);를 사용하여 사운드 클립 길이만큼 후에 실제 오브젝트를 파괴.
댓글남기기