Files
WhaleAdventure_VR/Assets/02_Scripts/Managers/GameManager.cs
2026-06-26 13:18:33 +09:00

75 lines
2.4 KiB
C#

using System;
using UnityEngine;
public class GameManager : MonoBehaviour,ISceneInitializable
{
public static GameManager Instance;
//현재 플레이어가 위치한 구역 (구역 상태의 단일 진실 출처)
public Zone CurrentZone { get; private set; } = Zone.None;
//구역이 바뀌면 발생. 사운드 등 여러 시스템이 구독해서 반응한다.
public event Action<Zone> OnZoneChanged;
private void Awake()
{
if (Instance == null)
{
Instance = this; //만들어진 자신을 인스턴스로 설정
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject); //이미 인스턴스가 있으면 자신을 파괴
}
}
//구역 변경 요청 (ZoneTrigger 등에서 호출)
public void SetZone(Zone zone)
{
if (zone == CurrentZone) return; //같은 구역이면 무시
CurrentZone = zone;
OnZoneChanged?.Invoke(zone); //구독자(SoundManager 등)에게 통지
}
public void OnSceneLoaded()
{
ResolveZoneAtSpawn();
}
//씬 로드 직후, 플레이어가 서 있는 위치에서 ZoneTrigger를 직접 조회해 구역을 확정한다.
//None을 깔고 OnTriggerEnter를 기다리는 방식의 BGM 글리치/누락(스폰 즉시 트리거 안인 경우)을 피하기 위함.
private void ResolveZoneAtSpawn()
{
Zone resolved = Zone.None;
var player = GameObject.FindGameObjectWithTag("Player");
if (player != null)
{
//콜라이더는 Awake/OnEnable에서 이미 물리씬에 등록되므로 첫 물리 스텝 전에도 즉시 조회 가능
Collider[] hits = Physics.OverlapSphere(
player.transform.position, 0.1f, ~0, QueryTriggerInteraction.Collide);
foreach (var hit in hits)
{
if (hit.TryGetComponent<ZoneTrigger>(out var trigger))
{
resolved = trigger.Zone;
break;
}
}
}
SetZone(resolved); //이전 구역과 같으면 dedup되어 BGM이 끊김 없이 이어진다
}
//게임 종료 (에디터에서는 플레이 모드 중지, 빌드에서는 앱 종료)
public void QuitGame()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
}
}