PlayerPrefs
로컬 저장소 기능으로, SetInt(), SetFloat(), SetString()을 사용해서 숫자, 실수, 문자열 데이터를 저장 가능하다.
게임이 꺼져도 데이터가 유지된다. (PlayerPrefs.Save()를 명시적으로 호출하지 않아도 자동 저장됨)
사용 방법
PlayerPrefs.SetInt("HighScore", 100);
PlayerPrefs.SetString("PlayerName", "Alex");
PlayerPrefs.Save(); // 저장 (자동으로 저장되므로 생략 가능)
- "HighScore" 키에 100 저장
- "PlayerName" 키에 "Alex" 저장
PlayerPrefs에서 데이터 불러오기
int score = PlayerPrefs.GetInt("HighScore");
string name = PlayerPrefs.GetString("PlayerName");
- "HighScore"에서 값 불러오기 (100 반환됨)
- "PlayerName"에서 값 불러오기 ("Alex" 반환됨)
Edit > Clear All PlayerPrefs 기능

모든 PlayerPrefs 데이터를 초기화하는 기능으로, 유니티 상단 메뉴에서 [Edit > Clear All PlayerPrefs] 클릭하면 저장된 데이터가 모두 삭제된다. 이후 PlayerPrefs.GetInt() 같은 함수를 호출하면 기본값(0 또는 빈 문자열)이 반환된다.
이 기능이 필요한 이유
1) 테스트 시 기존 데이터 초기화
- 개발 중 업적이나 설정 데이터가 꼬였을 때 기존 데이터를 삭제해서 테스트를 처음부터 다시 할 수 있음
2) 업적 시스템 초기화 시
- 특정 업적을 해금한 상태에서 다시 처음부터 잠금 상태로 테스트하고 싶을 때 실행하면 값이 0이 되어 다시 잠김
3) 저장된 데이터가 꼬였을 때 리셋
개발 중 PlayerPrefs를 잘못 저장하면 삭제 기능이 없어서 직접 수정하기 어려움.
Clear All PlayerPrefs를 실행하면 한 번에 싹 초기화 가능!
코드로 직접 초기화하는 방법
PlayerPrefs.DeleteAll(); // 모든 PlayerPrefs 데이터 삭제
PlayerPrefs.Save(); // 변경 내용 저장 (자동으로 저장되므로 생략 가능)

AchiveManager.cs
업적 시스템을 관리하는 스크립트로, 게임에서 특정 조건을 만족하면 새로운 캐릭터를 잠금 해제하고, 플레이어에게 알림(UI)을 보여주는 역할을 한다.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AchiveManager : MonoBehaviour
{
public GameObject[] lockCharacter; // 해금 전 캐릭터들을 저장하는 배열
public GameObject[] unlockCharacter; // 해금 완료된 캐릭터들을 저장하는 배열
public GameObject uiNotice; // 업적 달성 시 표시할 알림 UI
enum Achive { UnlockPotato, UnlockBean } // 열거형으로 업적을 정의
Achive[] achives; // 업적 데이터들을 저장할 배열
WaitForSecondsRealtime wait; // 코루틴에서 일정 시간 기다릴 때 사용하는 변수
void Awake()
{
// .GetValues(typeof()) = 주어진 열거형의 데이터를 모두 가져오는 함수
achives = (Achive[])Enum.GetValues(typeof(Achive)); // Achive 열거형에 있는 값들을 배열로 변환해서 achives에 저장
wait = new WaitForSecondsRealtime(5); // 5초 동안 기다리는 객체를 생성
// PlayerPrefs = 디바이스에 간단한 게임 데이터 저장 기능을 제공하는 유니티 클래스
if (!PlayerPrefs.HasKey("MyData")) { // PlayerPrefs에 MyData라는 키가 없으면
Init();
}
}
// 처음 실행될 때 업적 데이터 초기화
void Init()
{
PlayerPrefs.SetInt("MyData", 1); // MyData라는 키를 1로 설정하여 게임이 실행된 적 있다고 기록
// achives 배열을 반복하면서 모든 업적의 값을 0으로 초기화(잠금 상태)
foreach (Achive achive in achives) {
/* achive.ToString() = 업적의 이름을 문자열로 변환
* Achive.UnlockPotato.ToString() -> "UnlockPotato" */
PlayerPrefs.SetInt(achive.ToString(), 0); // 업적 이름을 키로 사용하여 0 저장(해당 업적 잠금 상태)
}
}
void Start()
{
UnlockCharacter();
}
// 업적 확인 후 잠금/해금 상태 반영
void UnlockCharacter()
{
// 배열을 순회하여 index에 해당하는 업적 이름 가져오기
for (int index = 0; index < lockCharacter.Length; index++) { // 잠금된 캐릭터 개수만큼 반복
string achiveName = achives[index].ToString(); // achives 배열에서 업적 이름을 가져옴
bool isUnlock = PlayerPrefs.GetInt(achiveName) == 1; // 업적 해금 여부 확인(1이면 해금 완료)
lockCharacter[index].SetActive(!isUnlock); // 잠겨있는 캐릭터 버튼 활성화/비활성화
unlockCharacter[index].SetActive(isUnlock); // 해금된 캐릭터 버튼 활성화/비활성화
}
}
/* LateUpdate()를 사용한 이유
* LateUpdate()는 모든 Update() 코드가 실행된 후 마지막에 실행되는 함수
* CheckAchive()는 업적 조건을 확인하는 함수로 만약 Update()에서 실행하면 GameManager.instance.kill
* 같은 변수가 업데이트되더라도 같은 프레임 내에서 조건이 완전히 반영되지 않을 가능성이 있음
* LateUpdate()를 사용하면 모든 Update() 로직이 끝나 변경된 값이 반영된 후 최종적으로 체크 가능 */
void LateUpdate()
{
// 모든 업적 확인
foreach (Achive achive in achives) {
CheckAchive(achive);
}
}
// 업적 달성 체크
void CheckAchive(Achive achive)
{
bool isAchive = false;
// 업적 별 다른 달성 조건문 작성
switch (achive) {
case Achive.UnlockPotato: // 감자 농부 해금 조건
isAchive = GameManager.instance.kill >= 100; // 100킬 이상
break;
case Achive.UnlockBean: // 콩 농부 해금 조건
isAchive = GameManager.instance.gameTime == GameManager.instance.maxGameTime; // 최초로 끝까지 생존
break;
}
// 해당 업적을 처음 달성했다는 조건문 작성
if (isAchive && PlayerPrefs.GetInt(achive.ToString()) == 0) { // 아직 해금되지 않았다면
PlayerPrefs.SetInt(achive.ToString(), 1); // 해당 업적 해금 저장
for (int index = 0; index < uiNotice.transform.childCount; index++) { // 업적 알림 UI의 모든 자식 오브젝트를 체크
bool isActive = index == (int)achive; // index가 현재 해금된 업적과 같을 때만 true
uiNotice.transform.GetChild(index).gameObject.SetActive(isActive); // index번째 자식 오브젝트를 가져와서 활성화/비활성화
}
StartCoroutine(NoticeRoutine());
}
}
// 알림 창을 활성화했다가 일정 시간 이후 비활성화하는 코루틴 생성
IEnumerator NoticeRoutine()
{
uiNotice.SetActive(true); // 알림 활성화
AudioManager.instance.PlaySfx(AudioManager.Sfx.LevelUp);
yield return wait; // 5초 대기
uiNotice.SetActive(false); // 알림 비활성화
}
}
'Unity > Undead Survivor' 카테고리의 다른 글
컨셉 예시 (0) | 2025.04.07 |
---|---|
싱글톤 패턴(Singleton Pattern) / 게임 매니저(Game Manager) / 오디오 매니저(Audio Manager) (0) | 2025.03.19 |
레벨업 시스템(LevelUp System) / 손과 무기 장착 표현(Hands) / 캐릭터 선택(Character Select) (0) | 2025.03.19 |
스크립터블 오브젝트(Scriptable Object) / 능력 업그레이드(Ability Upgrade) (0) | 2025.03.18 |
열거형(enum) / 월드 좌표(World Position)와 스크린 좌표(Screen Position) / HUD(Head-Up Display) (0) | 2025.03.18 |