using System.Collections.Generic; // 리스트 기능을 사용할거에요 -> System.Collections.Generic을 using UnityEngine; // 유니티 엔진의 기본 기능을 불러올거에요 -> UnityEngine을 /// /// 런 간 영구 저장되는 보스 카운터 잠금 해제 데이터. /// [System.Serializable] // 직렬화할거에요 -> 인스펙터나 JSON으로 저장 가능하게 public class BossCounterSaveData // 클래스를 선언할거에요 -> 저장할 데이터 구조체인 BossCounterSaveData를 { public bool dodgeCounterUnlocked = false; // 변수를 선언할거에요 -> 회피 카운터 해금 여부를 public bool aimCounterUnlocked = false; // 변수를 선언할거에요 -> 조준 카운터 해금 여부를 public bool pierceCounterUnlocked = false; // 변수를 선언할거에요 -> 관통 카운터 해금 여부를 /// 각 카운터가 발동된 총 횟수 public int dodgeCounterActivations = 0; // 변수를 선언할거에요 -> 회피 카운터 총 발동 횟수를 public int aimCounterActivations = 0; // 변수를 선언할거에요 -> 조준 카운터 총 발동 횟수를 public int pierceCounterActivations = 0; // 변수를 선언할거에요 -> 관통 카운터 총 발동 횟수를 } public class BossCounterPersistence : MonoBehaviour // 클래스를 선언할거에요 -> MonoBehaviour를 상속받는 BossCounterPersistence를 { public static BossCounterPersistence Instance { get; private set; } // 프로퍼티를 선언할거에요 -> 싱글톤 인스턴스 접근용 Instance를 private const string SAVE_KEY = "BossCounterData"; // 상수를 정의할거에요 -> 저장에 사용할 키 이름("BossCounterData")을 SAVE_KEY에 public BossCounterSaveData Data { get; private set; } // 프로퍼티를 선언할거에요 -> 실제 저장 데이터를 담을 Data를 private void Awake() // 함수를 실행할거에요 -> 스크립트 시작 시 호출되는 Awake를 { if (Instance != null && Instance != this) // 조건이 맞으면 실행할거에요 -> 이미 다른 인스턴스가 존재한다면 { Destroy(gameObject); // 파괴할거에요 -> 중복된 이 오브젝트를 return; // 중단할거에요 -> 초기화 로직을 } Instance = this; // 값을 저장할거에요 -> 내 자신(this)을 싱글톤 인스턴스에 DontDestroyOnLoad(gameObject); // 유지할거에요 -> 씬이 바뀌어도 이 오브젝트를 파괴하지 않게 Load(); // 함수를 실행할거에요 -> 저장된 데이터를 불러오는 Load를 } // ═══════════════════════════════════════════ // 잠금 해제 // ═══════════════════════════════════════════ /// 특정 카운터 타입을 영구 잠금 해제 public void UnlockCounter(CounterType type) // 함수를 선언할거에요 -> 카운터를 해금하는 UnlockCounter를 { switch (type) // 분기할거에요 -> 카운터 타입(type)에 따라 { case CounterType.Dodge: // 조건이 맞으면 실행할거에요 -> 회피 타입이라면 if (!Data.dodgeCounterUnlocked) // 조건이 맞으면 실행할거에요 -> 아직 해금되지 않았다면 { Data.dodgeCounterUnlocked = true; // 값을 바꿀거에요 -> 회피 해금 상태를 참(true)으로 Debug.Log("[BossCounter] 회피 카운터 영구 잠금 해제!"); // 로그를 출력할거에요 -> 해금 알림 메시지를 } break; case CounterType.Aim: // 조건이 맞으면 실행할거에요 -> 조준 타입이라면 if (!Data.aimCounterUnlocked) // 조건이 맞으면 실행할거에요 -> 아직 해금되지 않았다면 { Data.aimCounterUnlocked = true; // 값을 바꿀거에요 -> 조준 해금 상태를 참(true)으로 Debug.Log("[BossCounter] 조준 카운터 영구 잠금 해제!"); // 로그를 출력할거에요 -> 해금 알림 메시지를 } break; case CounterType.Pierce: // 조건이 맞으면 실행할거에요 -> 관통 타입이라면 if (!Data.pierceCounterUnlocked) // 조건이 맞으면 실행할거에요 -> 아직 해금되지 않았다면 { Data.pierceCounterUnlocked = true; // 값을 바꿀거에요 -> 관통 해금 상태를 참(true)으로 Debug.Log("[BossCounter] 관통 카운터 영구 잠금 해제!"); // 로그를 출력할거에요 -> 해금 알림 메시지를 } break; } Save(); // 함수를 실행할거에요 -> 변경된 데이터를 저장하는 Save를 } /// 카운터가 잠금 해제되어 있는지 확인 public bool IsUnlocked(CounterType type) // 함수를 선언할거에요 -> 해금 여부를 확인하는 IsUnlocked를 { return type switch // 반환할거에요 -> 타입에 따른 해금 변수 값을 { CounterType.Dodge => Data.dodgeCounterUnlocked, // 매칭되면 반환할거에요 -> 회피 해금 여부를 CounterType.Aim => Data.aimCounterUnlocked, // 매칭되면 반환할거에요 -> 조준 해금 여부를 CounterType.Pierce => Data.pierceCounterUnlocked, // 매칭되면 반환할거에요 -> 관통 해금 여부를 _ => false // 그 외에는 반환할거에요 -> 거짓(false)을 }; } /// 카운터 발동 횟수 기록 public void RecordActivation(CounterType type) // 함수를 선언할거에요 -> 발동 횟수를 기록하는 RecordActivation을 { switch (type) // 분기할거에요 -> 카운터 타입(type)에 따라 { case CounterType.Dodge: Data.dodgeCounterActivations++; break; // 일치하면 실행할거에요 -> 회피 발동 횟수를 1 증가시키기를 case CounterType.Aim: Data.aimCounterActivations++; break; // 일치하면 실행할거에요 -> 조준 발동 횟수를 1 증가시키기를 case CounterType.Pierce: Data.pierceCounterActivations++; break; // 일치하면 실행할거에요 -> 관통 발동 횟수를 1 증가시키기를 } Save(); // 함수를 실행할거에요 -> 변경된 횟수를 저장하는 Save를 } // ═══════════════════════════════════════════ // 저장 / 로드 / 리셋 // ═══════════════════════════════════════════ public void Save() // 함수를 선언할거에요 -> 데이터를 디스크에 저장하는 Save를 { string json = JsonUtility.ToJson(Data); // 변환할거에요 -> 데이터 객체를 JSON 문자열로 PlayerPrefs.SetString(SAVE_KEY, json); // 저장할거에요 -> JSON 문자열을 PlayerPrefs에 PlayerPrefs.Save(); // 실행할거에요 -> 변경사항을 디스크에 즉시 쓰기를 } public void Load() // 함수를 선언할거에요 -> 데이터를 불러오는 Load를 { if (PlayerPrefs.HasKey(SAVE_KEY)) // 조건이 맞으면 실행할거에요 -> 저장된 키가 존재한다면 { string json = PlayerPrefs.GetString(SAVE_KEY); // 불러올거에요 -> 저장된 JSON 문자열을 Data = JsonUtility.FromJson(json); // 변환할거에요 -> JSON을 데이터 객체로 복구해서 Data에 } else // 조건이 틀리면 실행할거에요 -> 저장된 데이터가 없다면 { Data = new BossCounterSaveData(); // 생성할거에요 -> 새로운 빈 데이터 객체를 } } /// 모든 영구 데이터 초기화 (디버그/뉴게임+) public void ResetAllData() // 함수를 선언할거에요 -> 모든 데이터를 초기화하는 ResetAllData를 { Data = new BossCounterSaveData(); // 초기화할거에요 -> 데이터 객체를 새 것으로 PlayerPrefs.DeleteKey(SAVE_KEY); // 삭제할거에요 -> 저장된 키를 Debug.Log("[BossCounter] 모든 보스 기억 데이터 초기화됨"); // 로그를 출력할거에요 -> 초기화 완료 메시지를 } }