Unityで使えるORマッパー作った話

  • 14
    Like
  • 0
    Comment
More than 1 year has passed since last update.

今回は、拙作のライブラリ、Nattoの話をさせていだきます。
https://github.com/adarapata/Natto
image

これは何?

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 にしてください。

  1. Unityプロジェクト内の任意の場所にclone git@github.com:adarapata/Natto.git

    • gitの使い方よくわからないという場合は、画面右下の Download ZIP からZIPを落として解凍してください。
  2. Assets/StreamingAssets/ 下にdbファイルを配置する(SQLiteの場合)

    • Unityはアプリケーション外にファイルを用意する場合、StreamingAssets という名前でディレクトリを作ると、ビルド時にそのまま吐き出してくれます。 ref ストリーミングアセット
  3. 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: パスワード

  1. 対応した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
これ使った方がみんな幸せになれそう

This post is the No.18 article of Unity Advent Calendar 2014