Unity で SQLite を使う例として「SQLiteUnityKit」を利用するプロジェクトの環境構築までは、前の記事で説明しました。
今回はその続きで、基本的な SQL 文を書いてみて、ちゃんと実行できるかをテストしてみました。
こんな感じで、うまくできました。
スクリプトの例
SQL を呼び出すスクリプト部分を、次のようにまとめてみました。
SQL 文(SQLiteUnityKit のクラス)をいろんなクラスが直接呼び出すのは、低レベルのコンポーネントと密接になりすぎるため、好ましいと思えなかった(not 疎結合)ので、アダプターみたいな役割のクラスを用意したところです。
インターフェースを挟むことで DB との結合も緩やかなものになっていいんだろうと思います。
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class SqlTester { private static string _fileName = "sample.db"; public static void Insert() { try { var db = new SqliteDatabase(_fileName); var rand = UnityEngine.Random.Range(2, 100); var name = $"athena No.{rand}"; var data1 = rand; var data2 = "arrow"; db.ExecuteQuery($"INSERT INTO charactors (name, data1, data2) VALUES ('{name}', {data1}, '{data2}')"); } catch { throw; } } public static void Update() { try { var db = new SqliteDatabase(_fileName); var power = UnityEngine.Random.Range(100, 1000); db.ExecuteQuery($"UPDATE charactors SET data1 = {power} WHERE id = 1"); } catch { throw; } } public static IEnumerable<string> Select() { var charactors = new List<string>(); try { 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 { throw; } return charactors; } }
テスト
ボタンを押下したときに、それぞれに対応する SqlTester
クラスのメソッドを実行します。
ボタンに設定したクラス
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class TestButton : MonoBehaviour { public event EventHandler<IEnumerable<string>> OccurredSelect; public void InsertSQL() { Debug.Log("Insert Called."); SqlTester.Insert(); } public void UpdateSQL() { Debug.Log("Update Called."); SqlTester.Update(); } public void SelectSQL() { Debug.Log("Select Called."); var charactors = SqlTester.Select(); OccurredSelect.Invoke(this, charactors); } }
テキストに設定したクラス
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>(); private string ExceptionText = ""; // Start is called before the first frame update void Start() { var test = GameObject.Find("SelectButton").GetComponent<TestButton>(); test.OccurredSelect += (owner, args) => { Debug.Log($"Called OccurredSelect Event at {nameof(Test)} Class."); var charactors = SqlTester.Select(); AddCharactors(charactors, true); }; try { var charactors = SqlTester.Select(); AddCharactors(charactors, true); } catch (Exception ex) { ExceptionText = ex.Message; } } // Update is called once per frame void Update() { if (OwnerObject == null) return; string text = ""; if (ExceptionText == "") { if (Charactors.Count > 0) { text = string.Join("\r\n", Charactors); } else { text = "キャラクターが存在しません"; } } else { text = ExceptionText; } OwnerObject.text = text; } private void AddCharactors(IEnumerable<string> charactors, bool isReset) { if (isReset) { Charactors.Clear(); } foreach (var chara in charactors) { Charactors.Add(chara); } } }
すこし小ネタとして、Select 文はイベント OccurredSelect
経由でデータをテキスト用のスクリプトクラスに渡しています。やり方はいろいろあると思います。最初に思いつきそうな Charactors プロパティを公開 (public) にして、別クラスが参照を得るのはイマイチに思ってこうしました。
- ユーザーには必要最小限の権限しか与えない
- 書き換えが不要なら、読み取り専用に作る
だと思います。なんで、Test クラスの Charactors プロパティは、いろんな他クラスに見えてたら(勝手にイジられる可能性があるのは)私の意図にありません。
テスト結果
Android でも問題なく動作しているようです。
なお、Windows 環境だと Unity Editor で利用している DB はどこにあるのか認識に注意が必要かもしれません。AppData 内にあるため %LOCALAPPDATA%\..\LocalLow\
といったショートカットが便利かもしれません。
%LOCALAPPDATA%..\LocalLow\"Player.CompanyName"\"プロジェクト名"
サンプル
今回作成したプログラムは GitHub に公開しています。
参考
Clean Architecture 達人に学ぶソフトウェアの構造と設計
- 作者:Robert C.Martin
- 発売日: 2018/07/27
- メディア: 単行本
Unityの教科書 Unity2019完全対応版 2D&3Dスマートフォンゲーム入門講座 (Entertainment&IDEA)
- 作者:北村 愛実
- 発売日: 2019/06/28
- メディア: 単行本
Using SQLite: Small. Fast. Reliable. Choose Any Three.
- 作者:Kreibich, Jay A.
- 発売日: 2010/08/27
- メディア: ペーパーバック