今回は、拙作のライブラリ、Nattoの話をさせていだきます。
https://github.com/adarapata/Natto
これは何?
Unity上でDBを操作するライブラリです。
MySQL5.6.14 SQLite3.8.74 で動作確認しています。
発端
自分のゲームにアイテム情報などを入れるときに、はじめはcsvやtxtファイルを取り込んで使っていたが、不満があった。
- データ打ち込むときに、面倒(txtだったら自分でカンマ区切りしたり、入力順番を意識したり)
- csvはセルを作りたくない、excel入れてない(Googleドライブ使えばいいけど)
なので、別の手段を考えてた時に、DB用意したらいいんじゃないのと思った。
DBで管理しようと思った理由
- その時にたまたまDBをよく触ってた
- 自分でフォーマット作らなくていい
- クライアントアプリが豊富
こっちがいろいろルール決めたり用意しなくても揃ってるので便利だなと思った。
だけど、アセットストアでそういうのないか探したら、だいたい有料だったので手が出せなかった。
https://www.assetstore.unity3d.com/jp/#!/content/3845
なので、勉強も兼ねて作ってみた。
そのときにRuby on Rails を触っていて、ActiveRecordの機能が便利だったので
それっぽいものに仕上がりました。
使い方
使い方はREADMEにだいたい載ってるので、補足説明だけやります。
0 . ProjectSetting->Player
から Api Compatibility Level
を .NET 2.0
にしてください。
- Unityプロジェクト内の任意の場所にclone
git@github.com:adarapata/Natto.git
-
Assets/StreamingAssets/
下にdbファイルを配置する(SQLiteの場合)
- Unityはアプリケーション外にファイルを用意する場合、
StreamingAssets
という名前でディレクトリを作ると、ビルド時にそのまま吐き出してくれます。
ref ストリーミングアセット
-
Natto/Resources/DatabaseConfig
に接続情報を設定する
上記ファイルは、MySQLもしくはSqliteに接続する際に必要な情報を保持するオブジェクトです。
Database Type
のプルダウンを切り替えると、DBの種類に応じて設定できる情報が切り替わります
SQLiteの場合
filename:
sqliteのファイル名。 StreamingAssets/
下のファイルが読み込まれる。
MySQLの場合
hostname:
ホスト名 db-hoge.com
or 111.111.1.1
など
username:
接続するユーザ名
database:
データベース名
port:
ポート番号
password:
パスワード
- 対応したDaoクラスを作成する。サンプル
public class SampleDao : ActiveRecord<SampleDao>
{
public override string tableName { get { return "SampleTable"; } }
public override string primaryKey { get { return "sample_dao_id"; } }
public int param_int { get { return GetInt("param_int"); } set { this["param_int"] = value; } }
public string param_string { get { return GetString("param_string"); } set { this["param_string"] = value; } }
public bool param_bool { get { return GetBool("param_bool"); } set { this["param_bool"] = value; } }
}
新規で作るクラスは ActiveRecord<T>
を継承しないといけません、
tableName
は対象のテーブル名を入れます。
primaryKey
はプライマリキーとなっているカラム名を入れてください。NattoはこのプロパティをキーとしてSQLを生成します。
レコードの値は、this["カラム名"]
の形式で取り出したり設定ができます。
ただ、すべてobject型で格納されているので利用する場合は下記メソッドを使ってそれぞれの型に変換して取り出したほうが良いです。
GetInt(key) // => int型で取得
GetIntOrNull(key) // => NULLもしくはint型で取得
GetFloat(key) // => float型で取得
GetFloatOrNull(key) // => NULLもしくはfloat型で取得
GetString(key) // => string型で取得
基本的には、サンプルのようにプロパティで隠蔽するような書き方を想定しています。
DB操作
取得
LINQ的な感じで取得できます
SampleDao dao = SampleDao.Find(n => n.param_string == "okame"); // カラム名 param_string が okame のレコードを取得する
List<SampleDao> manyDao = SampleDao.FindAll(); // テーブルの全レコード取得
List<SampleDao> whereDao = SampleDao.Where(n => n.param_int > 60); // カラム名 param_int が 60以上のレコードだけ取得
作成
SampleDao dao = new SampleDao { foo = "foo", bar = "bar" };
SampleDao.Create(dao); // => Void
更新
SampleDao dao = SampleDao.Find(n => n.id == 2);
dao.param_int = 100;
SampleDao.Update(dao); // => Void
削除
SampleDao dao = SampleDao.Find(n => n.id == 2);
SampleDao.Delete(dao);
注意点
全レコード取ってきてる
内部的には、FindAllで一旦全レコード持ってきてリストに保持しておき、それをその都度LINQで取り出しているだけです。
なので10万件とか100万件とかあるテーブルだと大変なことになります。
これは、小規模なDBでの利用のために作ったからです。(RPGの武器とかアイテムとかの各データ保持するとかそんなレベル)
あくまでExcelの代わりレベルでの利用を想定しています。
あとLINQを使いたかったからです。
SQLiteでパスワードが設定できない
だいたいこの記事に全て書かれていますが、利用しているdllが Mono.Data.SQlite
なのでパスワード設定ができません。
https://sites.google.com/site/nrapmed/unityrepo/unisqlite
System.Data.SQLite
はWindows限定なので、Macの自分には厳しく断念しました。
データの改造は自己責任でということで・・。
作ってみて
外側だけActiveRecordの丸パクリみたいなことしたけど、割と便利だった。
OSSなので、使っていてこうしたらいいのでは、などがありましたら修正してプルリクなど
送ってもらえると喜びます。
おまけ
無料でSQLite扱えるアセットが出ていました。
https://www.assetstore.unity3d.com/jp/#!/content/20660
これ使った方がみんな幸せになれそう