PlayerPrefs
Unity가 기본 제공하는 가장 간단한 로컬 저장 방식으로 소규모 설정값 등을 간단하게 저장하기에 좋다.
OS별 레지스트리 또는 설정 파일에 저장되며 파일 기반이 아니기에 가볍다.
하지만 암호화되지 않아 치트나 메모리 변조에 취약하다.
영구 저장이 가능하긴 하지만 대량 데이터에는 부적합하고 불편하다.
또한 이전에는 옵션값 등을 주로 썼지만, 요즘에는 옵션값을 로컬 환경이 아닌 계정 귀속으로 설정하는 경우가 많기에 이것도 조금 애매해졌다...
기본 사용법은 아래와 같다.
using UnityEngine;
using UnityEngine.InputSystem;
public class SaveTest : MonoBehaviour
{
public float playerHealth = 100;
void Start()
{
playerHealth = PlayerPrefs.GetFloat("Health");
Debug.Log(playerHealth);
}
void Update()
{
if (Keyboard.current.pKey.IsPressed())
{
playerHealth = 50;
PlayerPrefs.SetFloat("Health", playerHealth);
}
}
}
문제는 구조체나 클래스 같은 데이터를 저장하지 못하고 단순 Key - Value 기반이기 때문에 좌표 같은 걸 저장하려면
PlayerPrefs.SetFloat("PlayerX", pos.x);
PlayerPrefs.SetFloat("PlayerY", pos.y);
PlayerPrefs.SetFloat("PlayerZ", pos.z);
이렇게 작성해야하는 불편함과 비효율이 있다.
이걸 다시 Vector3로 옮겨야하기까지 하니 쓸 수는 있지만... 나는 별로 쓰고싶지 않다.
주로 옵션값, 설정, 혹은 로컬에 가볍게 저장할 필요가 있는 로그인 정보나 간단한 메타데이터 정도에 적합하다.
- 사용하면 좋은 상황
- 인게임 옵션 : 볼륨, 해상도, 단축키 등
- 튜토리얼 진행 여부 플래그
- 로그인한 계정 ID
- 최근 선택, 마지막 접속 등 메타 데이터
- 사용하면 안 좋은 상황
- 세이브 파일
- 보안이 필요한 데이터
- 좌표, DB 구조 등 계층화된 데이터
- 대량 데이터
JSON (JavaScript Object Notation)
문자열 기반의 객체 표현 방식으로 가독성이 높고 직렬화가 쉽다.
가볍고 직관적인 구조를 하고있어, 네트워크 / 로컬 저장 모두에 적합하다.
실제로 JSON 기반 서버 통신을 많이 하며, Firebase와 같은 서비스도 JSON 기반으로 되어있다.
프론트엔드 개발자에게는 매우 친숙한 친구다.
클래스 같은 건 바로 사용하지 못하고 직렬화를 해야 사용할 수 있다.
[System.Serializable]
public class PlayerData
{
public int hp;
public Vector3 position;
}
이제 이 클래스를 JSON 문자열로 변환해야하는데 유니티에서 JsonUtility 라는 아주 간편한 기능을 제공하고 있다.
string json = JsonUtility.ToJson(pd);
반대로 JSON 문자열을 다시 파싱하려면 아래처럼 작성하면 된다.
PlayerData loaded = JsonUtility.FromJson<PlayerData>(json);
실제 파일로 저장하려면 System.IO (Input Output)을 활용해야한다.
코드는 아래와 같다.
using UnityEngine;
using System.IO;
public class SaveTest : MonoBehaviour
{
public GameObject playerToSave;
private string filePath;
void Start()
{
filePath = Path.Combine(Application.persistentDataPath, "playerData.json");
Debug.Log("파일경로: " + filePath);
}
private void SaveData()
{
PlayerData pd = new PlayerData();
pd.hp = 100;
pd.position = playerToSave.transform.position;
string json = JsonUtility.ToJson(pd, true);
File.WriteAllText(filePath, json);
}
private void LoadData()
{
if (File.Exists(filePath))
{
string json = File.ReadAllText(filePath);
PlayerData loaded = JsonUtility.FromJson<PlayerData>(json);
playerToSave.transform.position = loaded.position;
}
}
}
게임 내 영구 저장 데이터 관리에 유용하다.
세이브 / 로드 에 유용하게 사용할 수 있고, 서버 통신에 주로 사용된다.
플레이어의 정보, 타일이나 유닛 배치 정보, 게임 진행 정보 등 폭 넓은 활용도를 생각할 수 있다.
- 사용하면 좋은 상황
- 세이브 / 로드 시스템
- 타일맵 / 월드 구조 저장
- 플레이어 스탯 및 인벤토리 저장
- 서버 통신
- 게임 설정, 빌드 설정, 커스텀 데이터 파일 등
- 사용하면 안 좋은 상황
- 프레임당 호출 같은 매우 빈번한 읽기/쓰기가 필요한 경우
- 대용량 데이터 (텍스쳐, 오디오 등)
CSV (Comma Seperated Values)
VSC 아님ㅎ
엑셀 기반의 데이터 테이블로, 행-열 단위 데이터 관리에 적합하다.
간편하게 데이터를 다룰 수 있기에 "구글 스프레드 시트로 DB 공짜로 쓰기" 같은 장난을 치는 사람들도 있다.
하지만 계층 구조 저장이 어렵기에 간단한 데이터 위주로 사용하는게 좋다.
정수/문자열 기반 테이블 데이터에는 뛰어나지만 계층화/중첩 구조에는 표현이 어렵다는 한계가 있다.
Unity 엔진에서 직접 CSV 파싱을 제공하지는 않기 때문에 직접 파싱하거나 서드파티를 사용해야한다.
단순하고 간단하지만 나열만 하면 되는 종류의 데이터 관리에 유용하다.
- 사용하면 좋은 상황
- 비개발자가 자주 편집하는 테이블 (스프레드 시트)
- 몬스터 스탯 목록
- 아이템 리스트
- 레벨 테이블
- 대량의 정형화된 행 기반 데이터
- 사용하면 안 좋은 상황
- 트리/계층 구조
- 복잡한 옵션
- 배열, 중첩 URL 등 구조적 데이터
- 런타임 중 수정/저장
ScriptableObject
Unity 에디터에서 제공하는 데이터 컨테이너로 에셋 형태로 데이터를 저장하고 관리할 수 있게 해준다.
Inspector에서 손쉽게 데이터 설정이 가능하여 비개발자 협업시에도 유용하며, 에셋으로 저장되기 때문에 작업 과정에서 재사용성이 매우 높다.
대규모 테이블 관리에 적합하며 오브젝트 간 공유 데이터로 적합하다.
단, 빌드 후에 런타임 중에는 .asset 파일이 생성이 불가능하여 아쉬운 부분이 있다.
ScriptableObject 정의
[CreateAssetMenu(fileName = "CubeData", menuName = "Scriptable Objects/CubeData")]
public class CubeData : ScriptableObject
{
public string cubeName;
public Vector3 scale;
}
활용 예시 - 큐브 스포너
if (Keyboard.current.qKey.isPressed)
{
var cube = Instantiate(prefab);
cube.transform.localScale = new Vector3(3, 3, 3);
}
public class CubeSpawner : MonoBehaviour
{
public CubeData[] mySO;
void Start()
{
transform.localScale = mySO[0].scale;
}
}
메서드는 추가할 수 없다.
그러므로 데이터만으로 구분되는 오브젝트를 관리하기에 좋다.
비슷하게 생겼지만 일부 데이터만 다른 유닛, 타워, 타일 등이 있을 수 있다.
- 사용하면 좋은 상황
- 유닛/타워/스킬/아이템 등 정적 데이터 관리
- MonoBehaviour와 분리된 데이터 컨테이너
- 직렬화된 초기값 관리
- Prefab 파라미터 분리
- 사용하면 안 좋은 상황
- 세이브/로드
- 플레이 중 지속적으로 변하는 데이터
- 플레이어 진행 정보 등 런타임 전용 데이터
Addressable
대규모 프로젝트를 위한 에셋 로딩/메모리 관리 시스템이다.
원격 저장소에서 에셋을 로딩할 수 있으며, 씬 간 공통 에셋 공유 및 패치 업데이트에 용이하다.
Resource 폴더의 단점을 보완하는 고급 구조다.
초기 설정이 번거롭다는 단점이 있지만 유용한 기능으로 대규모 게임에서 주로 활용된다고 한다.
- 사용하면 좋은 상황
- 모바일 환경에서 메모리 최적화 필요시
- 원격에서 DLC/패치 제공
- 씬 공통 에셋 공유
- 대규모 오픈월드 또는 많은 리소스
- 사용하면 안 좋은 상황
- 에셋 수가 적은 소규모 프로젝트
- 빌드 크기가 작고 업데이트 요구가 없거나 적은 게임
'Unity' 카테고리의 다른 글
| 네트워크 : OSI, TCP/IP, Client-Server, P2P (1) | 2026.01.05 |
|---|---|
| 길찾기 알고리즘 : 다익스트라(Dijkstra) 와 에이스타(A*) (0) | 2025.11.20 |
| Unity - Object Pool Pattern : 오브젝트 풀 (0) | 2025.11.12 |
| Unity - FSM : Finite State Machine - 유한 상태 머신 (0) | 2025.11.11 |
| Unity - 6000.2.10f1 - InputSystem 버그 (0) | 2025.11.07 |