目次
ユーザーごとのデータを管理するときに必要になりました。
UnityでSQLを使おうとするとDBMSのDllファイルをインポートしたり色々面倒そうなんで、アセットで済ませました。
一番売れてるこのアセットを買ったんですが、使い方についてちょっと戸惑ったのでメモ。
シンプルに使えるけど覚えるときはちょっとシンプルじゃなかった。
でも使ってみるとすごくシンプルに使える。
Awesome Assets.
Androidで使うときは、ツールのSimpleSQLのOptionから設定する必要があります。
SimpleSQLManagerのAwake内でデータベースファイルを開いているっぽいですが、シーンが変わる度に開いてます。シーンが切り替わるときに_manager.Close()でファイルを閉じないとエラーが出ると思います。そんなことなかった
前提
- SQL習得済み
- SQLite
- SQLの使い方には触れずにどんなアセットかについて書いてます。
データベースの拡張子を.bytesに変更する必要があります。.dbのままだと使えないみたいっす。
準備
とにかく必要なのが「Simple SQL Manager」コンポーネントを持ったオブジェクトです。一つのデータベースにつき一つ必要になります。
SimpleSQLManagerを通してデータベースにアクセスします。
シーン内に配置しましょう。
データベースのファイルについて
データベースのファイルがどんな風に扱われるか
アプリ起動時に、アプリ専用のフォルダ(Application.persistentDataPath)へデータベースファイルをコピーします。
例えば起動するとこんなファイルが、起動した端末のアプリ用のフォルダに作られます。
このデータベースに対して操作が行われるみたいです。
ちなみに、SQLManagerコンポーネントのChangeWorkingNameにチェックをいれると作成されるデータベースのファイル名を指定できます。
テーブルを作る
クラスをそのままテーブルにしたりできるのは便利。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
using SimpleSQL; using UnityEngine; class MyTable { //public int ID; みたいに普通の変数として宣言しても //カラムに追加されないみたいです [PrimaryKey]//主キーとして追加 public int ID { get; set; }//ゲッター、セッターとして宣言、定義する必要があるみたいです [NotNull]//ノットヌル public string Name { get; set; } public string Comment { get; set; }//属性を付けなくても良い public string From;//ただの変数はカラムに追加されない //カラムとしての制約を属性としてつけることが可能, //制約の詳細はドキュメントをみるべき } public class DBTest:MonoBehaviour{ void Start() { playerDb = GetComponent<SimpleSQLManager>(); playerDb.CreateTable<MyTable>(); } } |
↓こんな感じ。
でもSQLに慣れてれば普通に作った方がスムーズにいきそうな気もする。好みで。
クエリを使う
データの受け取りにはクラスを定義する必要があるようです。
列名と同じ名前のゲッターとセッターが呼ばれる感じみたいです。
たとえば、[weapon_name], [parts_name], [level], [quantity]という列名を持つデータベースがあったとき。
1 2 3 4 5 6 7 8 9 10 11 12 |
[Serializable] public class WeaponQuery { string weaponName; public string weapon_name { get => weaponName; set => weaponName = value; } string partsname; public string parts_name { get => partsname; set => partsname = value; } int _level; public int level { get => _level; set => _level = value; } float _quantity; public float quantity { get => _quantity; set => _quantity = value; } } |
こんな感じにすれば、ゲッターとセッターが呼ばれて、それぞれの変数に値が入ります。ゲッターの変数名が間違ってたら入りません。
いちいちクラス定義しないといけないのかと思ったけど、考えてみたらデータベースからデータを受け取るならどうしたってそうなる気がします。
データベースを更新するとき
プレイヤーのステータスなんかを、アプリがアップデートするたびに初期化してしまったらユーザーがキれちゃいます。
そういうときのためにSimpleSQLManagerには、OverWriteifExistsチェックがインスペクタ―から設定できます。
アプリ中で書き換えることのあるデータベースではこのチェックは外しておきます。
アプリによりますが、敵のデータなんかのずっと変わらないデータはチェックしてよいってドキュメントに書いてました。
プレイヤーに新しいステータスが追加されたときなど、動的なデータベースのデータ構造が変わったときには、古いデータベースを更新する必要があると思います。
その場合の処理は自分で実装しなさいって感じです。
ゲームデータを扱うなら避けて通れない問題だと思いますが。
公式のドキュメントによると、データベースにバージョンを付けて、その差に対応したメソッドを自分で定義するのがよくある方法だよって感じでした。
UpgradePathとかいうRDBMSの用語がある??
更新処理の一例(引用)
最新のデータベースのバージョンが3、古いバージョンが1,2とあったとしたとき。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
protected void dbupdate() { if (dbVersion == 1.0) { //ここでバージョン1から2への更新処理 dbVersion = 2//バージョンを更新する // update dbVersion in database to 2.0 } if (dbVersion == 2.0) { //ここでバージョン1から3への更新処理 dbVersion = 3.0; } } |
バージョンを取得して、内容を更新する処理をアプリが始まったときにやりなさいみたいな感じでした。例だと、バージョン1から3へ更新するときも、1から2の処理を飛ばさないようにしているみたいです。
この辺は自分でするしかなさそうです。
そういうわけでSimpleSQLでした
アプリ中のデータを、
ScriptableObjectを使ってアセットのデータとして扱うか、
RDBMSを使うか、
どれが良いのかわかりませんが、RDBMSにしてみたら、色々楽になった部分もありました。データの検索と更新の対象が全部RDBMSになったのでスクリプトがスッキリしたような気がしないでもないです。
そんなわけでSQLite使うなら良いアセットでした。やっぱりレビューが多いだけあるなって。
こういうゲーム内のそれなりに大きいデータってどう扱うのが良いんだろう?
都度考えるしかないのかな。