유니티에서 파일이나 웹(웹DB)등을 사용하지 않고 게임 정보를 저장하는 방법으로 PlayerPrefs를 제공합니다.
우리가 익숙한 윈도우 환경에서는 Registry랑 비슷한 개념인 거 같네요. (잘 모릅니다만 느낌이...)
검색해보면 이에 관해 잘 설명된 글이 나와 있더군요. 원문이 어느 것인지는 모르겠지만, 이 포스트의 관련 링크에 걸었습니다.
추석 전에 이를 사용해서 진행중인 level과 stage 등의 정보를 저장하는 것을 구현했습니다.
워낙 간단한 구현이라 작업도 쉽고 동작도 잘 되었습니다.
문제는 개별적인 데이터 저장 말고, Array와 같은 데이터들을 한꺼번에 저장하고 불러오는 것이었는데요.
이것도 추가 검색을 통해서 방법을 찾고 적용할 수 있었습니다.
사실 위 관련 링크 포스트에서 "좀 더 복잡한 데이터 저장하기" 내용을 따라 하면 되는 건데요.
문제는 제가 해당 코드를 제 프로젝트에 맞춰 똑같이 작성했는데 동작하질 않았던 것이었습니다.
검색을 통해 확인해보니 BinaryFomatter를 사용할 때에는, 직렬화할 객체에 [Serializable] 어트리뷰트를 설정하라는 글이 있더군요.
그래서 적용했더니... 이후에 잘 동작하는 것을 확인했습니다.
실제 PlayerPrefs를 통해 저장할 때에는 Array를 string 타입으로 바꾸어 저장하는 거 같았습니다.
아직 개발 단계라 적용하진 않았지만, 암호화/복호화도 해야겠지요.
혹시라도 안드로이드를 탈옥하거나 해킹해서 PlayerPref 저장 정보를 확인하고 고쳐버리면 안되니까요.
이전에 샘플 테스트를 통해 확인한 코드는 아래와 같습니다. (물론 이 코드도 인터넷 검색을 통해 구했습니다)
using System; // for encryption decryption
using System.Text; // for encryption decryption
using System.Collections; // for encryption decryption
using System.Security.Cryptography; // for encryption decryption
public string encryptData(string toEncrypt)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes("68914348997171234769693275831374"); // 임의의 난수 지정
// 256-AES key
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = rDel.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock (toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String (resultArray, 0, resultArray.Length);
}
public string decryptData(string toDecrypt)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes ("68914348997171234769693275831374"); // 지정했던 난수 활용
// AES-256 key
byte[] toEncryptArray = Convert.FromBase64String (toDecrypt);
RijndaelManaged rDel = new RijndaelManaged ();
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7;
// better lang support
ICryptoTransform cTransform = rDel.CreateDecryptor ();
byte[] resultArray = cTransform.TransformFinalBlock (toEncryptArray, 0, toEncryptArray.Length);
return UTF8Encoding.UTF8.GetString (resultArray);
}
이 작업까지 끝내놓으니, 기본적인 게임 진행과 저장은 구현이 되었네요.
NPC 대사라던가 레벨 데이터도 임시로 넣어놔서 빌드했습니다. 주변 분들께는 이제 플레이해보시라고 조금씩 보여드리고 있습니다. (하지만 다들 시큰둥한 반응을 ㅠㅠ)
앞으로 스킬 시스템과 튜토리얼 작업이 남았습니다.
둘 다 큰 작업인데, 완료되면 일반인에게 테스트를 요청해도 재미있게 하지 않을까 기대해 봅니다.
그게 끝나면 연출 부분과 사운드도 해야 하고, 최종적으로는 레벨 디자인 적용하고 QA 해야하는데...
역시 시간은 항상 모자라네요.
(물론 암호화 문제까지 된 것들도 있더군요.)
EditorPrefsPlus
Advanced PlayerPrefs Window
PlayerPrefsPlus
CryptoPlayerPrefs
Anti-Cheat Toolkit
기타 등등...