UnityでのSQLiteの使用(Unity + SQLite)

みなさん、こんにちは。この投稿では、UnityのSQLite Embedded Relational Databaseの操作に焦点を当てます。 この記事は、初心者向けにSQLiteの操作方法を示すことを目的として作成されたもので、SQLの基本を知っていることを前提としています。 インターネットには初心者向けの明確なチュートリアルがないため、このニッチを占有することにしました。 この記事では、このDBMSを操作するための簡単なクラスを作成します。このクラスは、さまざまなタスク(ローカリゼーション、データストレージ、さまざまなテーブルの保守)を解決するために使用できます。



SQLiteとは何ですか、なぜ必要なのですか?



SQLiteは、非常に人気のあるコンパクトな組み込みリレーショナルデータベース管理システムです。 SQLiteの重要な利点はクロスプラットフォームであるため、さまざまなプラットフォームでSQLiteを使用できます。 SQLiteは速度とコンパクトさが必要なときに使用できるため、データストレージの問題が発生した場合、このDBMSを使用して解決することにしました。



SQLiteの使用方法



データベースを作成および編集するには、ブラウザー用の多数の無料のユーティリティとプラグインがありますが、私は個人的にDBブラウザー(SQLite)を使用しますが、そのシンプルさに夢中になり、ブラウザーでさまざまなプラグインを操作するのはあまり便利ではないように思われました。 一般的に、それを望む人は誰でもそのように動作します。 DBブラウザーを使用すると、SQLを使用せずに、テーブルを安全に作成し、それらのテーブル間の接続を作成し、データを入力できます。 また、DBブラウザーでは、SQLiteを使用してペンですべてを実行できるため、ここでは誰かにとってより便利です。



テストデータベースを作成して入力する



プロジェクトのAssets / StreamingAssetsにデータベースを作成します(Unityはデータベースの* .bytesのみを理解するため、この拡張機能を使用しますので、 db.bytesがあります)。 純粋に、たとえば、次の表を使用してこのようなデータベースを作成しました。



1)プレーヤーの本質を説明する表「プレーヤー」:



CREATE TABLE "Player" ( "id_player" INTEGER NOT NULL, "nickname" TEXT NOT NULL, PRIMARY KEY("id_player") );
      
      





次のデータを入力しました:







2)データベースの正規化レベルを上げるために導入された表「スコア」



 CREATE TABLE "Scores" ( "id" INTEGER NOT NULL, "id_player" INTEGER NOT NULL, "score" INTEGER NOT NULL, PRIMARY KEY("id"), FOREIGN KEY("id_player") REFERENCES "Player"("id_player") );
      
      





次のデータを入力しました:







ライブラリを接続する



プロジェクトのAssets / StreamingAssetsにデータベースを作成し(db.bytesがあります)、このデータベースを操作するためにライブラリを接続する必要があります。 WindowsでSQLiteを使用するための公式サイトからsqlite3.dll ファイルをダウンロードします。 このACBDをAndroidと友達にするのに数日かかりました。 この記事に示されているライブラリが機能していないことが判明したため、私は個人的にAndroidで動作できず、エラーが絶えず増加しているため、これをインターネット上のどこかにアップロードしましたAndroid用ライブラリのバージョン 。 ここにライブラリを配置します-Assets / Plugins / sqlite.dllおよびAssets / Plugins / Android / sqlite.so



これらすべての操作の後、 System.Data.dllおよびMono.Data.Sqlite.dllC:\ Program Files(x86)\ Unity \ Editor \ Data \ Mono \ lib \ mono \ 2.0からコピーし、UnityプロジェクトのAssets / Pluginsを貼り付けます。 2018年バージョンでは、UnityはSystem.Data.dllが既に接続されており、2つの同一ファイルの競合があることを書き込む場合があることに注意してください。 実際、これは単純に解決され、新しく挿入されたSystem.Data.dllを削除しません。



ライブラリの構造は次のとおりです。



Assets / Plugins / Mono.Data.Sqlite.dll-必須:)

Assets / Plugins / System.Data.dll-同様の理由

Assets / Plugins / sqlite3.dll -WindowsでSQLiteを使用するため

Assets / Plugins / Android / libsqlite3.so -AndroidでSQLiteを使用するため



データベースを操作するスクリプトを作成する



そして最後に、作成したデータベースを操作するスクリプトの作成を開始できます。 最初に、MyDataBaseファイルを作成し、 System.DataMono.Data.SqliteSystem.IOライブラリを接続し、MyDataBaseクラスを静的にし、そしてもちろん、MonoBehaviourから継承を削除します。 データベースファイルの名前を持つ3つのプライベート変数と定数を追加します。 次のようなものを取得する必要があります。



 using UnityEngine; using System.Data; using Mono.Data.Sqlite; using System.IO; static class MyDataBase { private const string fileName = "db.bytes"; private static string DBPath; private static SqliteConnection connection; private static SqliteCommand command; }
      
      





もちろんこれはすべて良いことですが、データベースを操作することはできません。 データベースを操作するには、そのパスを取得する必要があります。データベースへのパスを取得する静的コンストラクターを作成することを提案します(データベースはStreamingAssetsにあることを思い出します)。



 static MyDataBase() { DBPath = GetDatabasePath(); } /// <summary>    .        ,      apk . </summary> private static string GetDatabasePath() { #if UNITY_EDITOR return Path.Combine(Application.streamingAssetsPath, fileName); #if UNITY_STANDALONE string filePath = Path.Combine(Application.dataPath, fileName); if(!File.Exists(filePath)) UnpackDatabase(filePath); return filePath; #elif UNITY_ANDROID string filePath = Path.Combine(Application.persistentDataPath, fileName); if(!File.Exists(filePath)) UnpackDatabase(filePath); return filePath; #endif } /// <summary>      . </summary> /// <param name="toPath">       . </param> private static void UnpackDatabase(string toPath) { string fromPath = Path.Combine(Application.streamingAssetsPath, fileName); WWW reader = new WWW(fromPath); while (!reader.isDone) { } File.WriteAllBytes(toPath, reader.bytes); }
      
      





ご注意 StreamingAssetsフォルダーには、ビルド後にReadOnly属性(Androidを除く)があり、何も書き込むことができないため、指定されたパス(Windowsの場合はApplication.dataPath / db.bytes for Android、 Application.persistentDataPath / db.bytes )でデータベースをアンパックする必要がありますその後、データベース内。 実際、データベースに何かを書き込むために、データベースをアンパックします。 この記事では、どのプラットフォームでどのパスを使用するかについて詳しく説明しています。



接続を開いて閉じるためのメソッドと、値を返す必要のない要求(INSERT、UPDATE、CREATE、DELETE、DROPなど)を実行するメソッドを作成します。



 /// <summary>      . </summary> private static void OpenConnection() { connection = new SqliteConnection("Data Source=" + DBPath); command = new SqliteCommand(connection); connection.Open(); } /// <summary>      . </summary> public static void CloseConnection() { connection.Close(); command.Dispose(); } /// <summary>     query. </summary> /// <param name="query">  . </param> public static void ExecuteQueryWithoutAnswer(string query) { OpenConnection(); command.CommandText = query; command.ExecuteNonQuery(); CloseConnection(); }
      
      





奇跡的に、スクリプトでデータ変更要求を実行できるようになりました。 しかし、非常に重要なSELECTはどうでしょうか? 1つの値を取得する場合、データ選択のクエリを実行するメソッドの戻り値はDataTable型または文字列にする必要があると判断しました。 これを行うには、2つのメソッドを記述します。



 /// <summary>     query    . </summary> /// <param name="query">  . </param> /// <returns>   1  1 ,   . </returns> public static string ExecuteQueryWithAnswer(string query) { OpenConnection(); command.CommandText = query; var answer = command.ExecuteScalar(); CloseConnection(); if (answer != null) return answer.ToString(); else return null; } /// <summary>    ,      query. </summary> /// <param name="query">  . </param> public static DataTable GetTable(string query) { OpenConnection(); SqliteDataAdapter adapter = new SqliteDataAdapter(query, connection); DataSet DS = new DataSet(); adapter.Fill(DS); adapter.Dispose(); CloseConnection(); return DS.Tables[0]; }
      
      





これで、データの変更と選択を要求できる簡単なスクリプトが完成しました。 今すぐScoreManagerスクリプトを書きましょう。 降順でソートされた最良の結果の表を受け取ります。 そして、確認のために、リーダーのニックネームとポイントをDebug.Logに表示します。



 using System.Collections; using System.Collections.Generic; using System.Data; using UnityEngine; public class ScoreManager : MonoBehaviour { private void Start() { //     DataTable scoreboard = MyDataBase.GetTable("SELECT * FROM Scores ORDER BY score DESC;"); //  id   int idBestPlayer = int.Parse(scoreboard.Rows[0][1].ToString()); //     string nickname = MyDataBase.ExecuteQueryWithAnswer($"SELECT nickname FROM Player WHERE id_player = {idBestPlayer};"); Debug.Log($"  {nickname}  {scoreboard.Rows[0][2].ToString()} ."); } }
      
      





起動時に得られるものは次のとおりです。







ご清聴ありがとうございました。建設的な批判を喜んで受け入れます。



All Articles