この記事は、Unity で SQLite を利用するために Standalone/Android 端末で SQLite DB ファイルを利用できる環境構築をまとめたものです。
- 開発環境、テスト環境
- 環境準備
- プラグイン ファイルのインポート(フォルダー設定)
- プラグイン ファイルのインポート
- スクリプトの準備(SQLiteUnityKit)
- サンプルの DB ファイルの用意
- テストコード
- 実行結果
- サンプル
- 参考
開発環境、テスト環境
開発環境
- Windows 10 (x64)
テスト環境
iOS は手元に環境がないため、以下で説明を省略していますが、考え方は同じです。
環境準備
最初に SQLite プラグイン ファイルと DB の編集用ツールを準備します。
SQLite プラグイン ファイルの説明
プラグイン ファイルの準備は、2つのポイントがあります。
まず、1つ目。現在は端末ごとに 32/64 ビットの両方に対応させる必要があります。
Android の64 ビット対応の基本的な設定について、認識がないかたは「64 ビット対応の記事」も参考に。
2つ目。Unity の期待するプラグイン ファイルの形式は端末によって異なることがあります。Windows は DLL
形式で、Android (Linux 1) のプラグイン形式は so
か aar
です。
そんなわけなので、端末ごとに別々のプラグイン ファイルを用意して設定することになります。(詳細は Unity マニュアル「Building plug-ins for desktop platforms」に詳しいです)
Windows/Android、そして、32/64 ビットの違いで別のプラグインを用意するわけなので、合計4種類のプラグイン ファイルが必要そうです……が、Android はAAR (Android ARchive) 形式のプラグイン ファイルの利用が現在は Unity で推奨されています。2
この AAR 形式は、32/64 ビットの違いや ARM アーキテクチャ 3 かどうかの違いを1ファイルでまとめて対応、設定できます。便利ですね。
一旦まとめましょう。
Windows 32/64 用の DLL ファイルに対応するのと、Android は AAR ファイル1つにおまかせ対応します。なので、合計3種類のプラグイン ファイルを準備・設定することになります。
補足すると Unity は ARM ではない 64 ビットに非対応、かつ、ARM ではない 32 ビット対応も Unity 2019.3 で完全に終了しているようです。 4
プラグイン ファイルのダウンロード
ダウンロードは、以下の SQLite 公式の SQLite.org からダウンロードします。(XXXXXXX はバージョンの番号を示します)
Windows 版は同じファイル名なので、解凍後はファイルが混ざらないように注意。
DB ブラウザーのダウンロード
SQLite のテーブル設計や確認は、別途ブラウザーを用意しておいたほうが便利です。なにか使い慣れたものを用意しておこう。
有償でもよければ navicat がオススメ。(RDBMS の商用ツール定番だと思う)非商用だと 12,000 円。
プラグイン ファイルのインポート(フォルダー設定)
入手したプラグイン ファイル(DLL/AAR)を Unity のプロジェクト内の「Assets」にインポートしていきます。
注意点があって、好き勝手にプラグイン ファイルを「Assets」フォルダー内にインポートすればいいわけではないです。
プラグイン ファイルは、次のように決まったフォルダーパスを作成し、それぞれに対応するプラグイン ファイルをインポートする必要があります。
プラットフォーム | CPU | パス | 補足 |
---|---|---|---|
Android | - | Assets\Plugins\Android | まとめて AAR ファイルを設定 |
Windows | x86 | Assets\Plugins\x86 | x86 DLL を設定 |
Windows | x64 | Assets\Plugins\x86_64 | x64 DLL を設定 |
一応、詳細は Unity マニュアル「Plugin インスペクター」などにまとめられています。
- Unity マニュアル - Plugin インスペクター
- Unity マニュアル - AAR プラグインと Android ライブラリ
- Google Play ガイド - 64 ビット アーキテクチャをサポートする
古い設定方法(.so
形式のインポート)は、有償の Unity Assets Store のツールを開き、「Package Content」などは実例として参考になります。
本記事の一番最後にも、同様の
.so
形式のファイルを直接インポートして設定したリポジトリーを公開しておきます(動作確認済)ただし、.so
形式のファイル作成自体が Windows 環境だと困難+Unity 推奨は AAR 形式みたいです。留意ください。
プラグイン ファイルのインポート
プラグイン ファイルのファイル名は、次のようにします。(XXXXXXX の部分はバージョン)
この名称変更で「libsqliteX」にするのは、必須です。どういうことかというと、Android 版のプラグイン ファイルの名前と一致させています。
補足として、一致させている AAR 形式のファイルは次のものです。
Android 版 インスペクター設定
インスペクターが Android
にチェックをつけているかどうか確認します。他の項目 Editor
や Standalone
は使用しないため、チェックをつけませんでした。
Windows 版 インスペクター設定
インスペクターは Any Platform
の選択を外して、Standalone
にチェックをつけます。私の開発環境は Windows 10 なので Editor
にもチェックをつけました。
Platform setting
も x86/x64
をそれぞれ設定します。これで、インスペクターの設定はこれだけで完了です。
環境ごとに、どのプラグイン ファイルを利用するのか設定したわけですね。
スクリプトの準備(SQLiteUnityKit)
SQLite を利用するためのスクリプト部分は、フリーの定番らしい SQLiteUnityKit を使ってテストすることにします。
SQLiteUnityKit は、マルチバイト文字(日本語)非対応のため注意。(別記事で、修正方法を掲載予定)
zip ダウンロード or リポジトリーのクローン、どちらでもいいと思います。
ダウンロードできたら、次の2つのファイルを取り出してください。Unity のプロジェクトに Assets\Scripts
フォルダーなどを作成して、次の2ファイルをインポートします。
- DataTable.cs
- SqliteDatabase.cs
インポートすると SqliteDatabase.cs
ファイルは、WWW クラスをしているコードの部分は UnityWebRequest クラスを使ってほしい旨の注意が表示されていました。
とりあえず重篤な問題ではないので、このままで続行します。
Sqlitedatabase.cs の変更箇所
DLL から関数をインポートしている部分を次のように変更します。
[DllImport("libsqliteX", EntryPoint = "sqlite3_open")] private static extern int sqlite3_open(string filename, out IntPtr db); [DllImport("libsqliteX", EntryPoint = "sqlite3_close")] private static extern int sqlite3_close(IntPtr db); [DllImport("libsqliteX", EntryPoint = "sqlite3_prepare_v2")] private static extern int sqlite3_prepare_v2(IntPtr db, string zSql, int nByte, out IntPtr ppStmpt, IntPtr pzTail); [DllImport("libsqliteX", EntryPoint = "sqlite3_step")] private static extern int sqlite3_step(IntPtr stmHandle); [DllImport("libsqliteX", EntryPoint = "sqlite3_finalize")] private static extern int sqlite3_finalize(IntPtr stmHandle); [DllImport("libsqliteX", EntryPoint = "sqlite3_errmsg")] private static extern IntPtr sqlite3_errmsg(IntPtr db); [DllImport("libsqliteX", EntryPoint = "sqlite3_column_count")] private static extern int sqlite3_column_count(IntPtr stmHandle); [DllImport("libsqliteX", EntryPoint = "sqlite3_column_name")] private static extern IntPtr sqlite3_column_name(IntPtr stmHandle, int iCol); [DllImport("libsqliteX", EntryPoint = "sqlite3_column_type")] private static extern int sqlite3_column_type(IntPtr stmHandle, int iCol); [DllImport("libsqliteX", EntryPoint = "sqlite3_column_int")] private static extern int sqlite3_column_int(IntPtr stmHandle, int iCol); [DllImport("libsqliteX", EntryPoint = "sqlite3_column_text")] private static extern IntPtr sqlite3_column_text(IntPtr stmHandle, int iCol); [DllImport("libsqliteX", EntryPoint = "sqlite3_column_double")] private static extern double sqlite3_column_double(IntPtr stmHandle, int iCol); [DllImport("libsqliteX", EntryPoint = "sqlite3_column_blob")] private static extern IntPtr sqlite3_column_blob(IntPtr stmHandle, int iCol); [DllImport("libsqliteX", EntryPoint = "sqlite3_column_bytes")] private static extern int sqlite3_column_bytes(IntPtr stmHandle, int iCol);
DllImport("sqlite3", EntryP...
となっていた部分の sqlite3
を libsqliteX
に変更しました。これは、プラグイン ファイルをインポートしたときのファイル名と一致させています。
Android 版 AAR ファイルを変更するよりも、dll のファイル名とスクリプトの宣言部分を変更して対応しました。(AAR ファイルも解説したとおり zip ファイルですが、再圧縮するくらいなら、こっちのほうが無難に思いました)
サンプルの DB ファイルの用意
SQLite の DB ファイルを作成します。 ここでは、こんなテーブルとデータを作成しました。
作成した DB ファイルは Assets\StreamingAssets
フォルダーを作成してインポートします。作成した StreamingAssets
も特別な意味をもつフォルダーになります。
ざっくり説明すると、StreamingAssets
フォルダーにインポートしたファイルは、ビルド先のプラットフォームでは、そのまま何も変換されない状態で展開されます。(ファイル圧縮が無い)
注意として StreamingAssets
フォルダーは readonly です。なので、StreamingAssets
フォルダーに DB ファイルがあっても insert も update もできません。そのため、persistentDataPath(アプリのインストール先のフォルダ)に DB ファイルをコピーする、といった手法が一般的になっているようです。
DB ファイルをコピーする操作は、SQLiteUnityKit の SqliteDatabase のコンストラクターが担当しています。(WWW クラスを利用して警告がでていた部分です)
テストコード
DB のデータを画面に表示する UI.Text に追加したスクリプトは次です。Owner Object
は自分自身 Text を設定します。
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; public class Test : MonoBehaviour { public Text OwnerObject; private List<string> Charactors = new List<string>(); // Start is called before the first frame update void Start() { try { var fileName = "sample.db"; var db = new SqliteDatabase(fileName); var query = db.ExecuteQuery("SELECT * FROM charactors"); foreach (var row in query.Rows) { var id = row["id"]; var name = row["name"]; var data1 = row["data1"]; var data2 = row["data2"]; var text = $"ID:{id}, Name:{name}, DATA1:{data1}, DATA2:{data2}"; Charactors.Add(text); } } catch (Exception ex) { Charactors.Add(ex.Message); } } // Update is called once per frame void Update() { if (OwnerObject != null && Charactors.Count > 0) { string text = ""; if (Charactors.Count > 0) { text = string.Join("\r\n", Charactors); } else { text = "キャラクターが存在しません"; } OwnerObject.text = text; } } }
実行結果
こんな感じになります。がはは、グッドだ!
Android でもやってみました。こんな感じでした。
サンプル
今回つくったプログラムは GitHub に公開しておきます。
AAR を使用したサンプル
.so ファイルを直接インポートしたサンプル
書ききれなかった部分があったので、補足として、もうひとつ記事「Unity SQLite の使い方 補足」を掲載します。こちらも参考になれば幸いです。
参考
- medium.com - SQLite and Unity: How to do it right.
- Qiita - 今更誰も教えてくれない、Unityにおけるアセット読み込みについての基礎知識
- Unityでオーディオを管理する その1 〜SQLの導入〜
- カヤック - Androidで情報をローカル保存するときの話
- テラシュールブログ - StreamingAssetsについて
- Android ABI
- Plugin インスペクター
Using SQLite: Small. Fast. Reliable. Choose Any Three.
- 作者:Kreibich, Jay A.
- 発売日: 2010/08/27
- メディア: ペーパーバック
- 作者:西沢 直木
- 発売日: 2009/05/19
- メディア: 大型本
-
一般的な Linux ディストリビューションとは異なるので、このあたりは wiki なども参考に。↩
-
Unity マニュアルより「AAR は、推奨される Unity の Android アプリケーションのプラグイン形式です。」(URL)↩
-
Android の ARM についても、認識が不足しているときは「Wiki - ARM architecture」や「Qiita - [ANDROID]CPUとアーキテクチャとABIの関係」などを参考に。↩
-
詳細は Untiy ブログの記事「Android サポートに関するお知らせ:64 ビット対応および App Bundle サポートの 2017.4 LTS バックポート」などを参考に。↩