멈추지 않고 끈질기게

[Unity][기타] 데이터 경로 관련 본문

Unity

[Unity][기타] 데이터 경로 관련

sam0308 2023. 10. 3. 15:44

※ 해당 포스팅은 개인의 공부 정리용 글입니다. 틀린 내용이 있다면 추후 수정될 수 있습니다.

※ 해당 포스팅은 하기 출처들을 참조하였습니다.

- https://docs.unity3d.com/ScriptReference/Application-dataPath.html

- https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html

 

 

0. 서문

 작업하던 포트폴리오 프로젝트에서 유저 데이터를 Resources 폴더가 아닌 다른 경로에 저장하고, Application.dataPath를 사용하여 접근해왔는데 안드로이드 빌드 후 실행해보니 데이터를 읽어오지 못하는 이슈가 발생했습니다. 찾아보니 데이터 경로에도 여러 종류가 있고, 플랫폼에 상관없이 빌드 상에서 읽기/쓰기 작업을 수행하려면 다른 경로를 사용해야 한다는 것을 알게 되었습니다. 

 

 

1. Application.dataPath

 Resources.Load()와 같이 자동으로 Assets/Resources 폴더를 타겟으로 하는 함수의 경우 경로 지정이 쉽지만, 그 외의 방법으로 파일 읽기/쓰기를 실행할 경우 파일 경로를 정확하게 지정해주어야 합니다. Application 클래스에는 이를 위한 static 문자열 변수를 제공하는데, 그 중 하나가 dataPath입니다. 

 

 Application.dataPath는 에디터 기준 "(프로젝트 폴더 경로)/Assets"를 반환합니다. 참고로 끝에 /가 없으므로, 경로를 덧붙이려면 /로 시작하여야 합니다(ex. Application.dataPath + "/Json/(파일명)"). 다음은 dataPath를 통해 Asset폴더 내 json 파일을 읽어들이는 코드 예시입니다.

// 데이터 저장용 클래스 선언
[Serializable]
public class StageData
{
    public int Hp;
    public int EnemyCount;
    public int MinEnemyId;
    public int MaxEnemyId;
    public int DropGold;
    public int DropGem;
}
[Serializable]
public class StageDataLoader
{
    public List<StageData> StageDatas;
}

public class JsonTest : MonoBehaviour
{
    void Start()
    {
        // 경로 지정
        string dataPath = Application.dataPath + "/Json/StageDatas.json";
        Debug.Log(dataPath);

        StageDataLoader loader = ReadJson(dataPath);
        foreach (StageData data in loader.StageDatas)
            Debug.Log(data.Hp);
    }

    StageDataLoader ReadJson(string path)
    {
        string jsonData = File.ReadAllText(path);
        return  JsonUtility.FromJson<StageDataLoader>(jsonData);
    }
}

사진 1. dataPath 사용 예시

 Application.dataPath에 Assets 폴더 하위 경로 "/Json/StageDatas.json"을 추가하여 File.ReadAllText()의 경로로 사용하였습니다. 로그 첫번째 줄을 보면 dataPath의 상세 경로를 확인할 수 있습니다(물론 프로젝트 폴더에 따라 달라집니다). 밑으로는 읽어들이기에 성공하여 각 StageData의 Hp 변수를 출력하는 모습입니다.

 

 dataPath는 프로젝트 창에서 쉽게 찾을 수 있는 경로라 에디터 상에서 사용하기에 편리하지만, 문제는 PC외의 플랫폼으로 빌드를 뽑아서 실행할 경우 해당 경로에서 파일을 찾을 수 없는 문제가 있습니다. 따라서 빌드에서 파일의 읽기/쓰기를 실행하려면 다른 경로를 사용해야 합니다.

 

 

2. Application.persistentDataPath

 Application.persistentDataPath는 각 운영 체제에서 허용하는 읽기/쓰기 가능한 폴더의 경로입니다. dataPath와 마찬가지로 하위 경로를 추가하려면 /로 시작해야 합니다(ex. Application.persistentDataPath + "/Json/StageDatas.json";). 읽기/쓰기 로직을  persistentDataPath를 사용하여 작성하면 빌드에서도  정상적으로 실행할 수 있습니다. 사실 읽기 작업은 데이터를 Resources 폴더에 넣어두고 Resources.Load()를 사용해도 되지만, 쓰기 작업의 경우 경로를 직접 지정해주어야 하므로 persistentDataPath를 사용해야 합니다.

 

const string GameDatapath = "/GameData.json";

public void SaveGameData()
{
    if (CurGameData == null)
        return;

    string jsonString = JsonUtility.ToJson(CurGameData);
    
    // persistentDataPath를 사용하여 경로 지정
    FileStream fileStream = new FileStream(Application.persistentDataPath + GameDataPath, FileMode.Create);
    byte[] data = Encoding.UTF8.GetBytes(jsonString);
    fileStream.Write(data, 0, data.Length);
    fileStream.Close();
}

 상기 코드는 포트폴리오 프로젝트에서 유저 데이터를 저장하는 함수를 수정한 것으로, persistentDataPath를 사용하는 방식으로 바꾼 이후 안드로이드 빌드에서 정상적으로 쓰기 작업이 실행됨을 확인할 수 있었습니다.

 

 


 이 외에도 Application 클래스에는 consoleLogPath, temporaryCachePath와 같은 경로 전달용 문자열 변수가 있었으나, 해당 변수들은 아직 사용해 본 일이 없어서 생략했습니다. 일단 존재를 기억해두고, 추후 사용해보고 정리할만큼의 내용이 나오면 추가하도록 하겠습니다.