Files
StoryGame_Unity/Assets/02_Scripts/Managers/LocationManager.cs
2026-07-24 18:20:02 +09:00

86 lines
2.9 KiB
C#

using UnityEngine;
// 게임 씬에 하나. 현재 장소 프리팹을 띄우고, 장소 안 캐릭터 슬롯들의 등장 여부를 갱신한다.
// DialogPlayer가 대화 후보를 조회할 때 (Database, Current)를 여기서 가져간다.
public class LocationManager : MonoBehaviour
{
public static LocationManager Instance { get; private set; }
[SerializeField] private StoryDatabase _database;
[Tooltip("장소 프리팹을 붙일 부모 (비우면 이 오브젝트)")]
[SerializeField] private Transform _locationRoot;
[Tooltip("게임 시작 시 입장할 장소")]
[SerializeField] private LocationData _startLocation;
public StoryDatabase Database => _database;
public LocationData Current { get; private set; }
private GameObject _currentInstance;
// 대화 중 진행도/트리거가 바뀌었을 때의 슬롯 갱신 예약.
// 대화 도중 화자를 꺼 버리면 재생이 깨지므로, 대화가 끝난 뒤로 미룬다.
private bool _refreshPending;
private void Awake()
{
if (Instance != null && Instance != this) { Destroy(gameObject); return; }
Instance = this;
if (_locationRoot == null) _locationRoot = transform;
}
private void Start()
{
if (StoryManager.Instance != null)
StoryManager.Instance.Changed += OnStoryChanged;
DialogPlayer.AnyActiveChanged += OnDialogActiveChanged;
if (_startLocation != null)
MoveTo(_startLocation);
}
private void OnDestroy()
{
if (Instance != this) return;
if (StoryManager.Instance != null)
StoryManager.Instance.Changed -= OnStoryChanged;
DialogPlayer.AnyActiveChanged -= OnDialogActiveChanged;
Instance = null;
}
// 장소 이동 (이동 버튼의 UnityEvent 연결용). 대화 중에는 무시된다.
public void MoveTo(LocationData location)
{
if (location == null || DialogPlayer.IsAnyActive) return;
Current = location;
if (_currentInstance != null) Destroy(_currentInstance);
_currentInstance = location.Prefab != null
? Instantiate(location.Prefab, _locationRoot)
: null;
RefreshSlots();
}
// 대화로 진행도/트리거가 바뀌면 등장 캐릭터도 달라질 수 있다
private void OnStoryChanged()
{
if (DialogPlayer.IsAnyActive) { _refreshPending = true; return; }
RefreshSlots();
}
private void OnDialogActiveChanged(bool active)
{
if (active || !_refreshPending) return;
_refreshPending = false;
RefreshSlots();
}
private void RefreshSlots()
{
if (_currentInstance == null || _database == null) return;
foreach (var slot in _currentInstance.GetComponentsInChildren<CharacterSlot>(includeInactive: true))
slot.Refresh(_database, Current);
}
}