Table of Contents
Cocos2dx(js) で作成したアプリを Unity で作り直してアップデートした際、アプリ領域に保存したデータの移行を行ったので手順について記載します。
移行させるデータについて
Android における SharedPreferences と同様に、Cocos2dx では cc.sys.localStorage によってテキストや数値といったデータを保存できます。
// 例:キーと値のペアで数値データを保存する
cc.sys.localStorage.setItem("number", 123);
cc.log(cc.sys.localStorage.getItem("number"));
Cocos2dx でこのように保存したデータは SQLite3 によるデータベースとしてアプリ領域に保存されます。保存されるデータベースのファイル名は jsb.sqlite です。OSごとの保存パスは以下のようになっています。
Android では通常 data/data/[パッケージ名]/databases/jsb.sqlite iOS では /var/mobile/Containers/Data/Application/[アプリ固有ID]/Documents/jsb.sqlite
従って、Cocos2dx の保存データを Unity で読み込むためには、SQLite のテーブルから情報を取り出す処理が必要になります。
UnityでSQLiteを使うには
SQLite を扱う基本的なコードは以下からダウンロードできます。
このフレームワークに含まれる2つのソースコード(DataTable.cs、SqliteDatabase.cs)とSQLiteの実行ファイル libsqlite3.so を使用します。libsqlite3.so が含まれていますが、最新版をダウンロードしたい場合は”SQLite Download Page“から取得できます。
もしファイルが適切なディレクトリにあるにも関わらず、以下のようなエラー(DllNotFoundException)が出た場合はダウンロードし直してみると良いかも知れません。
ダウンロードした libsqlite3.so を、使いたい Unity のプロジェクトの Plugins ディレクトリに保存します。OSごとに保存するディレクトリが以下のように異なります。
Androidの場合
実行環境別にコピーして保存します。
Assets/Plugins/Android/libs/x86/libsqlite3.so Assets/Plugins/Android/libs/armeabi-v7a/libsqlite3.so Assets/Plugins/Android/libs/arm64-v8a/libsqlite3.so
Unity のインスペクターで、各実行環境に向けて設定(Platform Setting > CPU)を変更しておきます。
iOSの場合
以下のディレクトリに保存します。
Assets/Plugins/iOS/libsqlite3.so
SQLiteのデータベースを読み込むコード
libsqlite3.so の準備が終わったら、実際にデータを読み込むためのコードを用意します。
SqliteDatabase.cs を開き、コンストラクタから不要な機能を除去します。
/// <summary>
/// Initializes a new instance of the <see cref="SqliteDatabase"/> class.
/// </summary>
/// <param name='dbName'>
/// Data Base name. (the file needs exist in the streamingAssets folder)
/// </param>
public SqliteDatabase (string pathDB)
{
// 不要な機能を覗いたコンストラクタ
this.pathDB = pathDB;
}
また、マルチバイト文字を扱う予定があるのであれば、メソッド Prepare の書き換えを行います。
private IntPtr Prepare(string query)
{
IntPtr stmHandle;
// クエリのバイト数を取得するように変更
int byteCount = System.Text.Encoding.UTF8.GetByteCount(query);
if (sqlite3_prepare_v2(_connection, query, byteCount, out stmHandle, IntPtr.Zero) != SQLITE_OK)
{
IntPtr errorMsg = sqlite3_errmsg(_connection);
throw new SqliteException(Marshal.PtrToStringAnsi(errorMsg));
}
return stmHandle;
}
以上の修正を終えたら、これを用いて SQLite からデータを読み取る処理を行うスクリプトを作成します。
例えば、以下のような関数を作成し、アプリ起動時に実行するようにします。
void ConvertOldData() {
// 初回起動に一度だけ行うようにする
if (PlayerPrefs.GetString("Convert") == "DONE") {
print("読み込み済み");
return;
}
string dbFilename = "jsb.sqlite";
// 見つかったSQLiteデータベースのパスを格納する変数
string cocosDataPath = "";
#if UNITY_ANDROID
string packageName = "your.app.package.name";
// 念の為、データベース保存の候補となりそうなディレクトリを検索
string[] possibleDataPaths = {
"data/data/" + packageName + "/databases/" + dbFilename,
"data/user/0/" + packageName + "/databases/" + dbFilename,
"/mnt/sdcard/Android/data/" + packageName + "/databases/" + dbFilename,
"/storage/emulated/0/Android/data/" + packageName + "/databases/" + dbFilename,
};
foreach (string path in possibleDataPaths) {
if (File.Exists(path)) {
print("FILE FOUND AT: " + path);
cocosDataPath = path;
break;
}
print("SEARCHED: " + path);
}
if (cocosDataPath == "") {
print("NO FILE FOUND");
return;
}
#elif UNITY_IOS
cocosDataPath = Application.persistentDataPath + "/" + dbFilename;
if (!File.Exists(cocosDataPath)) {
print("NO FILE FOUND AT: " + cocosDataPath);
return;
}
#endif
// Cocos2dx で作成されるデータテーブル名は data なので
string tableName = "data";
SqliteDatabase sqlDB = new SqliteDatabase(cocosDataPath);
// データ取得
string selectQuery = "select * from " + tableName;
SqliteDataTable dataTable = sqlDB.ExecuteQuery(selectQuery);
// データベースにある全てのキーと値のペアを取得
foreach (DataRow row in dataTable.Rows)
{
string key = (string)row["key"];
string val = (string)row["value"];
print(key + ": " + val);
}
}
iOS では、保存パスは Application.persistentDataPath を使って簡単に取得できます。
Application.persistentDataPath + "/jsb.sqlite";
Android では、機種によって保存領域が異なる可能性があるため、念の為複数のディレクトリを確認していますが、通常は data/data/[パッケージ名]/databases/ 以下に保存されるはずです。
以上のコードによって、保存されたキーと値のペアが取得できますので、それをそのまま利用したり PlayerPrefs に保存し直したりすることができます。
Cocos2dxのデータを読み込む際の注意点
cc.sys.localStorage で保存したデータは Unity で読み込んだ場合、全て文字列として扱われます。
よって、PlayerPrefs に保存し直したりする場合、元々数値やブール値で保存したものはパースによって数値(intやfloat)やブール値(true/false)に変換する必要があります。
// 数値の取得とパース
int result;
if (int.TryParse(val, out result)) {
PlayerPrefs.SetInt(key, result);
}
float resultF;
if (float.TryParse(val, out resultF)) {
PlayerPrefs.SetFloat(key, resultF);
}
// bool の取得とパース
bool getBool;
if (key == "flag") {
getBool = (val == "true");
}
以上、Cocos2dx製アプリの保存データをUnity製アプリに移行する方法についてでした。





