
게임을 만들 때, 지금까지 해왔던 작업 상황들을 세이브/로드하는 것은 중요하다.
.json 파일로도 세이브와 로드를 할 수 있는데, 이 때는 Unity의 저장 경로에 대한 지식이 필요하다.
Application.dataPath는 읽기 전용으로, 런타임에 파일 작성, 수정이 불가능하다.
Assets 폴더Application.streamingAssetsPath는 읽기 전용으로, 런타임에 파일 작성, 수정이 불가능하다.
서버에서 다운받는 데이터를 서버가 마련되지 않아 파일 형식으로 Unity에 포함시킬 때 사용한다.
Application.persistentDataPath는 읽기/쓰기 겸용으로, 특정 운영체제에서 앱이 사용할 수 있도록 허용한 경로를 말한다. 따라서 운영체제마다 경로가 모두 다르다.
나는 Windows를 사용하다가 Linux Mint Cinnamon으로 넘어온 사람이기에 Windows만 쓸 때는 되던게 안되서 매우 당황했던 기억이 있다...
데스크탑의 운영체제들에서는 File.ReadAllText()를 이용하여 StreamingAssets 경로에 위치한 파일에 접근하는 것이 가능하다.
하지만 Android에선 StreamingAssets 경로는 압축된 APK 내부에 있기 때문에 File.ReadAllText()를 이용하여 정상적으로 StreamingAssets 경로에 위치한 파일에 접근할 수 없다.
따라서 UnityWebRequest를 이용하여 우회하는 방법을 사용해야 한다.
예를 들어 StreamingAssets 경로에 UnitData.json이 위치하며 이를 Android에서 로드해야 한다고 하자.
제일 먼저 생각할 수 있는 방법은 File.ReadAllText()를 활용하는 방법이다.
private void Awake()
{
m_unit_data_path = Path.Combine(Application.streamingAssetsPath, "UnitData.json");
LoadJson();
}
private void LoadJson()
{
if(!File.Exists(m_unit_data_path))
{
return;
}
var json_data = File.ReadAllText(m_unit_data_path);
... // 이후의 json_data에 대한 처리
}
하지만 Android에서는 StreamingAssets 경로에 접근할 수 없다. 따라서 UnityWebRequest를 사용한다.
private m_is_loaded; // 이 컴포넌트가 데이터를 로드하는 동안,
public IsLoaded // 다른 오브젝트에서 참조하는 것을 방지하기 위함
{
get => m_is_loaded;
private set => m_is_loaded = value;
}
private void Awake()
{
m_unit_data_path = Path.Combine(Application.streamingAssetsPath, "UnitData.json");
LoadJson();
}
private LoadJson()
{
IsLoaded = false;
StartCoroutine(LoadJsonAsync());
}
private IEnumerator LoadJsonAsync()
{
var www = UnityWebRequest.Get(m_unit_data_path);
yield return www.SendWebRequest();
if(www.result != UnityWebRequest.Result.Success)
{
Debug.Log($"{m_unit_data_path}를 로드하는 데 실패했습니다.");
Debug.Log($"다음을 참고해주세요. 오류 내용: {www.error}");
return;
}
var json_data = www.downloadHandler.text;
... // 이후의 json_data에 대한 처리
IsLoaded = true;
}
Unity의 저장 경로에 이에 따른 특성들을 미리 알아둔다면 좀 편리하게 작업할 수 있을 것이다.