diff --git a/Assets/01_Scenes/BossScene.unity b/Assets/01_Scenes/BossScene.unity index c94e4d9..9a72996 100644 --- a/Assets/01_Scenes/BossScene.unity +++ b/Assets/01_Scenes/BossScene.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b72ab2bd177dd4658cea02681eaf7ef0dd72c46e10522ec25b9380d5b3dea439 -size 212561 +oid sha256:5d0d2e66691c6d953076a04620cce947a84336bf491ddd9c53c7196216661e0b +size 212564 diff --git a/Assets/01_Scenes/GameScene.unity b/Assets/01_Scenes/GameScene.unity index 6178771..977434a 100644 --- a/Assets/01_Scenes/GameScene.unity +++ b/Assets/01_Scenes/GameScene.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a094601dfda7d787c784156243abd46e9a35b1653d8ee2f3531ff04cc38454c -size 167965 +oid sha256:8e92b73760ba8ea7e03dbb12f5090e52824dd3d981a04544412385262253902f +size 168830 diff --git a/Assets/02_Scripts/Combat/PlayerWeaponInventory.cs b/Assets/02_Scripts/Combat/PlayerWeaponInventory.cs index 6300598..077d914 100644 --- a/Assets/02_Scripts/Combat/PlayerWeaponInventory.cs +++ b/Assets/02_Scripts/Combat/PlayerWeaponInventory.cs @@ -6,8 +6,16 @@ // PlayerWeaponInventory // ---------------------------------------------------------------------------- // 플레이어가 보유한 무기 목록 + 현재 장착 무기 관리. +// 씬 전환 시에도 데이터를 유지하기 위해 DontDestroyOnLoad 싱글톤으로 동작. // PlayerController가 OnWeaponChanged 이벤트를 구독해서 애니메이션/공격 콤보 교체. // +// 사용법: +// - 어디서든 PlayerWeaponInventory.Instance 또는 EnsureInstance()로 접근. +// - 인스턴스가 없으면 EnsureInstance()가 새 GameObject로 자동 생성 → 첫 씬에 +// 수동 배치하지 않아도 됨. +// - Player 프리팹에는 이 컴포넌트를 더 이상 붙이지 않는다 (중복 시엔 자동 폐기되긴 하지만, +// 프리팹과 같은 GameObject가 영속화되는 부작용을 피하려면 제거 권장). +// // 슬롯 매핑 (외부 코드의 EquipSlot 인덱스): // -1 → 맨손 (CurrentWeapon == null) // 0 → 첫 번째로 픽업한 무기 @@ -21,9 +29,40 @@ // ============================================================================ public class PlayerWeaponInventory : MonoBehaviour { + // ─── 싱글톤 ────────────────────────────────────────────────────────── + public static PlayerWeaponInventory Instance { get; private set; } + + // 어디서든 호출하면 인스턴스를 보장한다. 없으면 새 GameObject로 생성. + // (PlayerController.Awake에서 호출해 첫 진입을 보장하는 용도) + public static PlayerWeaponInventory EnsureInstance() + { + if (Instance != null) return Instance; + GameObject go = new GameObject(nameof(PlayerWeaponInventory)); + return go.AddComponent(); + // AddComponent가 Awake를 동기 호출 → Instance 세팅 + DontDestroyOnLoad 적용 완료 후 반환. + } + private readonly List _weapons = new(); private int _currentIndex = -1; // -1 = 맨손 + private void Awake() + { + // 중복 생성 방지 — 이미 Instance가 있으면 이 컴포넌트만 폐기. + // (GameObject 전체를 지우지 않는 이유: Player 프리팹 등에 잘못 붙어 있어도 Player가 사라지면 안 되니까.) + if (Instance != null && Instance != this) + { + Destroy(this); + return; + } + Instance = this; + } + + private void OnDestroy() + { + // 앱 종료 등으로 영속 인스턴스가 파괴될 때 정적 참조 정리. + if (Instance == this) Instance = null; + } + // 무기 교체 시 발화. null이면 맨손. public event Action OnWeaponChanged; diff --git a/Assets/02_Scripts/Combat/WeaponPickup.cs b/Assets/02_Scripts/Combat/WeaponPickup.cs index f7b91fe..c0f6212 100644 --- a/Assets/02_Scripts/Combat/WeaponPickup.cs +++ b/Assets/02_Scripts/Combat/WeaponPickup.cs @@ -43,13 +43,16 @@ private void ApplyVisual() } // 플레이어가 트리거 영역에 진입 시 발화. - // Player(또는 자식)에 PlayerWeaponInventory 컴포넌트가 있어야 픽업 됨. + // 인벤토리는 영속 싱글톤(PlayerWeaponInventory.Instance)이므로 Player 본인이 들어왔는지만 확인. // 이미 보유 중이면 Pickup이 false 반환 → pickup 오브젝트 그대로 유지. private void OnTriggerEnter2D(Collider2D other) { if (_weapon == null) return; - PlayerWeaponInventory inventory = other.GetComponentInParent(); + // 플레이어 본인만 픽업 (적/투사체 등이 트리거 들어와도 무시). + if (other.GetComponentInParent() == null) return; + + PlayerWeaponInventory inventory = PlayerWeaponInventory.Instance; if (inventory == null) return; if (inventory.Pickup(_weapon)) diff --git a/Assets/02_Scripts/Player/PlayerController.cs b/Assets/02_Scripts/Player/PlayerController.cs index 8e257c2..1bb5d1c 100644 --- a/Assets/02_Scripts/Player/PlayerController.cs +++ b/Assets/02_Scripts/Player/PlayerController.cs @@ -150,10 +150,9 @@ private void Awake() // 공격이 enemy를 hit하면 _lastHitEnemy를 기억 → 다음 잡기에서 그 enemy를 우선 타겟팅. _attackHitbox.OnHit += OnAttackHit; - // 무기 인벤토리: 같은 GameObject에 컴포넌트가 없으면 자동 부착. - _weaponInventory = GetComponent(); - if (_weaponInventory == null) - _weaponInventory = gameObject.AddComponent(); + // 무기 인벤토리: 영속 싱글톤 (DontDestroyOnLoad). 없으면 EnsureInstance가 새로 생성. + // 씬 전환 시 PlayerController는 파괴되지만 인벤토리는 살아남아 무기 목록을 유지한다. + _weaponInventory = PlayerWeaponInventory.EnsureInstance(); _weaponInventory.OnWeaponChanged += OnWeaponChanged; } diff --git a/Assets/02_Scripts/UI/WeaponInventory.cs b/Assets/02_Scripts/UI/WeaponInventory.cs index 20789fb..e66c8c5 100644 --- a/Assets/02_Scripts/UI/WeaponInventory.cs +++ b/Assets/02_Scripts/UI/WeaponInventory.cs @@ -13,7 +13,7 @@ // // _slots는 데이터가 아니라 생성한 화면 오브젝트 캐시일 뿐 (재사용 풀). // ============================================================================ -public class WeaponInventory : MonoBehaviour +public class WeaponInventory : MonoBehaviour, ISceneInitializable { [SerializeField] private PlayerWeaponInventory _wInvenSource; // 비워두면 런타임에 자동 탐색 [SerializeField] private Transform _slotRoot; // 슬롯이 생성될 부모 @@ -33,6 +33,7 @@ private void Start() Refresh(); } + private void OnDestroy() { if (_wInvenSource != null) @@ -40,6 +41,17 @@ private void OnDestroy() } + public void OnSceneLoaded() + { + if (_wInvenSource == null) + _wInvenSource = FindFirstObjectByType(); + + if (_wInvenSource != null) + _wInvenSource.OnInventoryChanged += Refresh; + + Refresh(); + } + // 인벤토리 상태를 화면에 반영. 슬롯 개수를 무기 수에 맞추고 내용/하이라이트 갱신. private void Refresh() { @@ -61,4 +73,5 @@ private void Refresh() _slots[i].SetSelected(i == _wInvenSource.CurrentIndex); } } + } diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset index 60d7447..3763740 100644 --- a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae51c05513b9403b5534f7d06d6e4ac8e2b4fc7531647bace8ea7e8d332b0810 -size 553740 +oid sha256:a73237e48a3b6c0164ad0ffd483edeb7f27dab722aaf42dada64a71c184dbdd7 +size 25217