물에 살고싶은 개발자

SimpleJson과 유니티PlayerPrefs를 이용한 간단한 데이터저장과 불러오기 본문

Unity3D

SimpleJson과 유니티PlayerPrefs를 이용한 간단한 데이터저장과 불러오기

돼지사랑 2016. 1. 6. 19:55

게임을 개발하다 보면 어떻게든 데이터를 저장해야 할 일이 생긴다.

(그러지않는다면 옛날 오락실게임처럼 전원을 껏다키는것만으로도 데이터가 날아가기 때문에..)

문제는 데이터저장을 어떻게 하느냐는 것이다. 나처럼 사수도 없이 혼자서 게임을 개발하다가 데이터저장을 어떻게하지..? 라는 생각이 떠오르게 된다면 은근 많이 난감해진다. 어떻게해야할지 막막해지기 때문이다.


구글링을 통해봐도 마땅한 상담글이나 질문글이 없고, 뭘 써라 뭘 써라 라는 얘기들은 많지만 내가 할수있는것은 유니티와 게임로직짜는정도밖에 못하는데 SQL이 어쩌고 NoSQL이 어쩌고 서버가, 패킷이 어쩌고 이런글들이 막 우르르 튀어나와서 오히려 더 혼란스러워 지기만 한다. 사실 그런부분까지 다 다룰줄 알고 그런 고차원(?) 글들을 전부 이해할 수 있다면 참 좋겠지만..안타깝게도 나는 그저 남들보다 논리력이 조금 더 좋아 프로그래밍이 적성에 맞는 비기너일뿐이다. 


이번엔 그런의미에서 책을 통해 알게된 SimpleJson과 유니티에서 지원하는 PlayerPrefs를 이용한 간단한 DB구축과 세이브, 로드에 대한 포스팅을 할것이다.


아, 물론 이 포스팅은 서버개발자,클라사수,디비개발자들중 단 한명이라도 옆에 있거나, 혼자서 디비구축,서버구축이 가능한 능력자들에겐 아무 의미없으므로,(그리고 부끄러우므로ㅠㅠ) 다른곳을 찾아보는것이 시간을 효율적으로 사용할 수 있을것이다.


-------------------------------------------------------------------------------------------------------


미리 얘기하는 것이지만, 사실 이 방법은 (모바일환경)1인개발 인디게임이나 프로토타입을 제작하는데에는 쓸만할지 몰라도 그외에는 큰 의미가 없다. 구글링을 통해 안 사실이지만 PlayerPrefs의 경우 보안이 매우 취약하고 간단한 데이터를 다룰때만 살짝 써서 생산성을 올리자는 취지에서 지원하는 기능이기에, DB대용으로 쓰는건 무리가 있다.(아니, 매우 많다.)


아무튼 본론으로 들어가자면, 일단 먼저 PlayerPrefs을 살펴보자.

놀랍게도 아주 간단하게 이용할 수 있다.


PlayerPrefs.SetInt( Key , value );
PlayerPrefs.GetInt( Key , value );

PlayerPrefs.HasKey(key);
PlayerPrefs.DeleteKey(key);


이게 끝이다. 클래스선언이고뭐고 다 필요없다. 아니 정확히는 지원하는 함수가 몇개 더있지만, 그것은 그냥 레퍼런스를 찾아보거나 ctr+space로 제목을 보면 어떤기능인지 짐작이 가는것들이니 굳이 설명하지않겠다.

사실 위에 코드에 있는것들도 보면 그냥 알수있다. Set자료형은 저장 Get자료형은 로드 HasKey는 있는지 확인 DeleteKey는 키 삭제. 아주 단순하다.


그럼 이제 SimpleJson쪽을 살펴보자. (PlayerPrefs는 저걸로 끝이다. 더 설명할게 없다. 저것만 알면 그냥 쓰면된다.)

내가 갖고있는 유니티 강좌책에서는 이렇게 표현하고 있다.

"유니티에서 JSON을 사용하려면 JSON을 분석 및 빌드할 수 있는 JSON파서가 필요하다. (생략) SimpleJson은 간단하고 사용법이 간단하다는 장점이 있다. 복잡한 C# 고급 문법을 사용하지 않고도 쉽게 사용할 수 있다는 점이 필자가 선택한 이유다." 

그렇다. 내가 이 포스팅에서 굳이 SimpleJson을 사용하는 이유도 쉬워서다. 

http://wiki.unity3d.com/index.php/SimpleJSON 여기에 가면 다운받을수도 있다.(무료다)

(참고로 이 정보는 "절대강좌! 유니티3D Unity3D전문 개발자가 알려주는 효과적인 제작기법" -이재현 지음- 위키북스 출판 책에 있는 정보다. 출처밝히는거다.)


일단 다운받은걸 임포트하면 Plugins 폴더가 생기고 그 안에 SimpleJSON.cs파일이 있을것이다. 그것만 있으면 된다.준비끝이다.(일단 Json이 xml을 대체하기 좋은 통신언어가 뭐 어쩌고 하는 json에 대한 얘기는 다 집어치우자. 궁금하다면 따로 검색하면 우르르 나온다.) 


일단 Json의 문법을 알아야 하는데 문법이 너무 간단하다. 프로그래밍을 모르는 사람도 가능할듯하다. 직접 보자

(참고로 Json파일의 확장자는 .json이다. 그냥 cs파일 아무거나 만든다음 확장자만 바꿔줘도 쓸수있다.)


{

"이름" : "홍길동",

"성별" : "남",

"직업" : "의적" , 

"능력치" : { "레벨":25 , "생명력":580 , "신통력" : 870 "기력" : 1020 },

"보유스킬" : [ "변신술" , "순간이동술" ]

}


이런식이다. 처음보는 문법인데 매우 친숙하다. 그냥 이 문법만 맞춰서 작성해주면 된다. 그럼 이번엔 실제로 C#에서 어떻게 쓰이는지 코드로 알아보자.


void Test()
{
	TextAsset Json = Resources.Load( "json/jsonfile" );
	string JsonStr = Json.text;
	
	var JsonData = JSON.Parse( JsonStr );
}


이렇게 해두면 준비 끝이다. 이렇게 준비가 됏다면 그 다음엔 

void Test()
{
	TextAsset Json = Resources.Load( "json/jsonfile" );
	string JsonStr = Json.text;
	
	var JsonData = JSON.Parse( JsonStr );
	
	string[] Skill;
	
	for( int i = 0 ; i < JsonData.Count ; i++ )
	{
		Skill[i] = JsonData["보유스킬"][i];
		Debug.Log( Skill[i] );
	}
	Debug.Log( JsonData["이름"] );
	Debug.Log( JsonData["능력치"]["레벨"] );
}


이런식으로 활용하면 된다. 아주 심플하다. 헷갈릴거같다 싶으면 그냥 다차원 배열 쓰듯이 쓰면 된다고 생각하면 된다. 이제 이걸 어떻게 활용해야 간단하게 보관할까에 대해 고민해보자.

SimpleJson을 이용해 친숙한 문법을 자랑하는 Json문법에 초기 데이터를 잡아주고, 그걸 코드에서 꺼내는 방법은 알았는데, 매번 제이슨에서 꺼내면 코드가 더러워질 우려가 있다.

그래서 여기에서 딕셔너리가 등장한다. (딕셔너리에 대한건 따로 검색해보시라)


처음 초기화할때(Start,OnEnable등) PlayerPrefs과 Json파일에 있는 정보들을 HasKey를 통해 모두 비교해준다.

그 다음 PlayerPrefs과 모두 같다면, 딕셔너리에 PlayerPrefs에 있는 키,벨류값들을 전부 넣어준다.

만약 한개라도 PlayerPrefs이랑 다른게 있다면, Json파일에 있는 데이터들을 로드시켜서 딕셔너리에 쫘르륵 넣어주고, 별도로 함수를 만들어 foreach를 이용해 딕셔너리의 키값과 벨류값을 PlayerPrefs으로 세이브해준다.

이렇게 해서 게임로직에서 데이터가 필요할때나 수정해야할때 딕셔너리값을 이용하고, 딕셔너리값을 수정한 다음 위에서 별도로 만든 세이브함수를 한번 싹 불러준다. 이렇게하면 딕셔너리에 있는 데이터 테이블대로 PlayerPrefs에 저장되고 어플리케이션을 껏다켜도 데이터는 온전히 유지가 된다.


방법론적으로 보면 이렇다. 

이 방법은 사실 그렇게 효율적이지 않다. 세이브함수를 할때마다 딕셔너리의 개수만큼 foreach문을 돌려야하고 

Json을 저런식으로 핸들링하는것 자체가 연산양이 쓸데없이 소모되어 꽤나 비효율적이다. 하지만, 만들고자 하는 게임의 스케일이 최적화에 관한부분을 민감하게 받아들여서 만들어야할만큼 크지 않고, 오히려 하드코딩을 해도 요즘 하드웨어들이 하드캐리를 해서 큰 문제가 없다면 써볼만한 방법이다.


나도 얼마전까지는 무조건 최적화하기 좋게, 무조건 확장성을 생각해서, 무조건 효율적으로, 무조건 가독성 좋게 코딩을 해야한다고 생각했지만, 지금은 상황에 맞게 코딩하는것이 가장 좋은거라고 생각한다. 

만약 제작중인 게임의 스케일이 미친듯이 크고 하필이면 모바일플랫폼이라면 연산량하나하나 텍스쳐 하나하나에 신경을 써야겠지만, 반대로 저예산 소규모스케일의 게임을 제작한다면, 위에서 설명한 방법처럼 비효율적이고 말도안되는 방법이라도 심플하고 쉬운방법으로 해서 빠르게 제작하는것이 맞을수도 있다. 

내가 생각하기에 능력있는 프로그래머란, 다른 무엇보다도 상황에 맞는 적절한 코딩스타일을 선택할 수 있는 프로그래머라고 생각한다.(나비효과를 예측하는 노하우와 프로그래밍 지식의 깊이는 당연한것이므로 제외했다.)


아무튼..마무리가 안되니까 이대로 끗!

Comments