ABOUT ME

천리 길도 한 걸음부터

Today
Yesterday
Total
  • Land Of Memories - Data Save - JSON
    유니티 프로젝트/RPG-2D

    이번 작업은 유니티를 종료할 때 위치를 저장하고

     

    새로 시작할 때 해당 위치로 불러오는 작업을 했습니다.

     

    사용 방식은 저장할 데이터를 JSON 문자열로 저장을 하였으며,

     

    불러올 때 JSON 문자열을 객체로 변환해 주었습니다.

     

     

    JSON을 사용할 때 "왜 사용하는가?"에 대한 질문을 사수분께 한 적이 있습니다.

     

    일반 바이너리로 데이터가 저장된 파일을 볼 경우

     

    00101010 01000011 00001111... 과 같은 데이터로 저장이 되기에 사람이 봐도 어떤 의미인지 알 수 없는 반면

     

    JSON 같은 경우에는 저장된 파일이

     

    {                       

       "level": 10,   

    "hp": 1000.

    }                      

     

    과 같이 텍스트 형태로 저장이 되기에 직접 수정도할 수 있을뿐더러 바로 이해하기 편하다.

     

    라는 답변을 받은적이 있습니다.

     

     

    저장된 데이터 파일을 열어서 볼 기회가 없어서, 아직 몸소 체험을 하진 못했지만

     

    어떠한 의미인지만 알아 들은채로 끝났던 기억이 있는데

     

     

    이번 기회에 JSON에 대해 좀 더 알아보았습니다.

     

    1. 범용성

    "다양한 언어와 플랫폼에서 지원이 된다"

     

    2. 경량 데이터 구조

    "XML 간은 다른 텍스트 기반 형식보다 간결하다"

    "데이터 크기가 작아 네트워크 전송 속도와 저장 공간 측면에서 효율적이다"

     

    3. 많은 시스템이 JSON 형식을 사용해 데이터를 저장하거나 로그를 남긴다.

     

    이 외에는 가독성 및 파일 수정 및 관리가 용이하다는 이야기가 많았습니다.

     


     

    우선 Manager 스크립트를 생성해 주었습니다.

     

    스태틱 변수로 instance가 선언되었으며,

     

    Manager가 로드되면 "instance = this"가 실행됩니다.

     

    또한 씬 전환이 될 시

     

    DontDestroyOnLoad()를 사용하여 오브젝트가 유지되며

     

    이미 생성된 instance가 있으므로 새로운 Manager는 삭제가 됩니다.

     

    즉 게임 내에서 단 하나의 Manager만 유지되도록 하였으며

     

    다른 스크립트에서 DataManager에 접근을 하기 위해 public으로 받아온 코드입니다.

     

     


     

     

    다음은 DataManager 스크립트입니다.

     

     Manager에 접근하여 불러질 스크립트인데요.

     

    로블록스에서도 DataManager의 이름을 사용했었는데 기억이 새록새록합니다.

     


     

    코드를 위에서부터 보겠습니다.

     

    playerLastPositionX, playerLastPositionY

    변수는 플레이어의 X, Y 값을 저장할 변수입니다.

     

    폴더의 경로는

    위 경로로 사용했는데요.

     

    Application.persistentDataPath 와 같은 코드를 보자면

     

    유니티에서 자동으로 생성해 주는 폴더 라고 합니다.

     

     

    뒤에 /playerLastPosition.json은 폴더 경로에 이름을 지정해 주는 것입니다.

     


     

     

    먼저 데이터를 저장하는 함수입니다.

     

    현재 사용하고 있는 바는 플레이어의 마지막 위치를 저장하는 기능을 수행합니다.

     

    첫 번째로 JsonUtility.ToJson() 코드는 유니티에서 제공하는 직렬화 메서드 라고 합니다.

     

    인자로 this 키워드를 넣어 '나 자신'을 가리키며

     

    playerLastPositionX와 playerLastPositionY를

     

    JSON 형식으로 변환을 하게 됩니다.

     

     

    File.WriteAllText() 파일에 데이터를 쓰기(write) 위한 메서드입니다.

     

    뒤에 인자로는 

     

    savePath 경로에 json(JSON 형식으로 변환된 데이터)를 기록한다고 보시면 됩니다.

     


     

     

    다음은 데이터를 읽어올 때 사용될 함수입니다.

     

    File.Exists() 함수는 여러 가지 찾아보다가 알게 된 함수인데

     

    File.Exists() 특정 경로(savePath)에 파일이 존재하는지 확인하는 함수라고 보시면 됩니다.

     

    파일이 존재하지 않으면 오류를 발생시킨다고 합니다.

     

     

    또한 쓰기와 달리 File.ReadAllText(savePath) 코드를 살펴보자면

     

    지정된 경로에 있는 파일의 내용을 문자열로 읽어 오는 함수입니다.

     

     

    즉 JSON 형식으로 된 데이터를 json 변수에 저장하는 구현입니다.

     

     

    마지막으로 JsonUtility.FromJsonOverwrite(json, this)는

     

    JSON 문자열을 읽어서 객체로 변환한 후에 this(DataManager)에 값을 덮어쓰는 코드입니다.

     

    현재 playerLastPositionX, playerLastPositionY 두 변수가 존재하며

     

    각가 값이 playerLastPositionX = 20, playerLastPositionY = 10 일경우

     

    playerLastPositionX = 20

    playerLastPositionX = 10

     

    과 같은 형태가 됩니다.

     


     

    다음은 PlayerMovmement 스크립트에 추가를 했습니다.

     

     

    Start() 이벤트 함수에 추가를 하였으며

     

    데이터를 불러오고 transform (player)의 포지션을 저장된 값으로 이동시켜 주는 모습입니다.

     

     

     

    OnApplicationQuit() 함수는 유니티에서 게임이 종료될 때 실행되는 함수입니다.

     

    게임이 종료되거나, 에디터에서 멈출 때 호출되며 테스트하기에도 아주 용이했습니다.

     

     

    함수 내부를 보면 SavePlayerPosition() 함수를 호출합니다.

     

    SavePlayerPosition() 함수 내에선

     

    각 DataManager의 변수 값을 현재 값으로 수정을 한 뒤 

     

    DataSaveLastPosition()를 호출하여 데이터를 저장합니다.

     

     

    유니티 및 에디터를 종료 후 확인해 보면 다음과 같이 파일이 저장되어 있는 모습을 볼 수 있습니다.


     

    현재 제가 원하는 건 플레이어가 이동 후 재접속했을 때 종료할 때의 위치로 리스폰되는 것입니다.

     

     

     

     

     

    잘 되는 것 같습니다!

     

    데이터를 사용해서 Level이나 Hp 등 여러 가지를 사용할 수도 있을 것 같습니다.

     

     

    비하인드(?) 스토리로 이번에 살짝 새롭게 느낀 게

     

    코드를 작성하고 "끝!" 이 아닌 한 발자국 멀리 떨어져서 다시 보는 법도 필요하다고 생각이 들었습니다.

     

     

    스크립트를 작성하고 이동을 할 때마다 데이터를 저장하는 방식으로 초기에 구현을 했었는데,

     

    막 이것저것 찾아보면서 구현 작업을 할 때에는 '음 이게 무조건 맞아~'라고 생각했던 것도

     

    다른 작업 완료 후 일지를 작성하려고 보니깐

     

    '굳이?'라는 생각이 바로 들었습니다.

     

    살짝 장기나 오목 같은걸 하면은 당사자는 눈에 잘 안들어오는데

     

    나 보다 못하는 제3 자가 훈수 둘 때 훨씬 더 잘 보는 느낌..?

     

     

    결국 OnApplicationQuit() 이벤트 함수를 사용해서 원하는 결과물을 얻어내긴 했는데

     

    뭔가 기분이 좋거나 싫거나 하는게 아닌 음... 그냥 뭔가 '아차!' 싶었습니다 ㅎㅎ

     

     

     

    또한 뭔가 저장해야 할 데이터가 늘어났을 때

     

    각각 개별로 하는 것이 아닌 '저장' 버튼을 하나 만들어 두는 게 관리는 둘째치고

     

    사용자에게 더 편한가..? 를 생각 중에 있습니다.

     

    OnApplicationQuit() 함수를 이용해서 DataManager에 위치를 변경시키고

     

    저장할 데이터들은 Manager에 선언해서 사용하면? 

     

    이라고 잠깐 생각해 봤습니다.

     

    이게 맞는 것 같기도 하고? 아닌 것 같기도 하고?

     


     

    뭔가 이번 일지는 코드 설명보다 글이 훨씬 많았는데요, 제 지식 상승만 된 것 같습니다 ㅎㅎ

     

     

    현재 Land Of Memories 의 계획은 간단한 UI 와

     

    '재미 요소'를 추가 시키려고 하고 있습니다.

     

    빠르진 않더라도 천천히 한걸음씩 나아 가겠습니다.

     

     

    감사합니다.

     

     

     

     

    댓글

김효겸 / Tel. 010-7735-0580 / E-mail. dollzzang2@hanmail.net