Verwenden von SQLite in Unity (Unity + SQLite)

Hallo allerseits, dieser Beitrag konzentriert sich auf die Arbeit mit der SQLite Embedded Relational Database von Unity. Dieser Artikel wurde von einem Anfänger für Anfänger mit dem Ziel verfasst, Ihnen die Arbeit mit SQLite zu zeigen. Es wird davon ausgegangen, dass Sie die Grundlagen von SQL kennen. Da es im Internet kein klares Tutorial für Anfänger gibt, habe ich mich entschlossen, diese Nische zu besetzen. In diesem Artikel schreiben wir eine einfache Klasse für die Arbeit mit diesem DBMS, mit der eine Vielzahl von Aufgaben (Lokalisierung, Datenspeicherung, Pflege verschiedener Tabellen) gelöst werden können.

Was ist SQLite und warum brauchen wir es?


SQLite ist ein kompaktes eingebettetes relationales Datenbankverwaltungssystem, das sehr beliebt ist. Ein wichtiges Plus von SQLite ist die plattformübergreifende Nutzung, sodass wir SQLite für verschiedene Plattformen verwenden können. SQLite kann verwendet werden, wenn Geschwindigkeit und Kompaktheit erforderlich sind. Im Falle eines Datenspeicherproblems habe ich mich daher entschlossen, es mit diesem DBMS zu lösen.

Wie arbeite ich mit SQLite?


Um unsere Datenbank zu erstellen und zu bearbeiten, gibt es eine große Anzahl kostenloser Dienstprogramme und Plug-Ins für Browser. Ich persönlich werde DB Browser (SQLite) verwenden, es hat mich mit seiner Einfachheit begeistert und es schien mir nicht sehr bequem, mit verschiedenen Plug-Ins im Browser zu arbeiten. Im Allgemeinen funktioniert es so, wer es will. Mit DB Browser können Sie auf einfache Weise Tabellen erstellen, Verbindungen zwischen ihnen herstellen und sie mit Daten füllen, ohne auf SQL zurückgreifen zu müssen. Außerdem können Sie im DB-Browser mit SQLite alles mit Stiften tun. Hier ist es für jemanden bequemer.

Erstellen und füllen Sie eine Testdatenbank


Wir erstellen eine Datenbank in den Assets / StreamingAssets unseres Projekts (ich habe es db.bytes, da Unity nur * .bytes für Datenbanken versteht, werden wir diese Erweiterung verwenden). Ich habe zum Beispiel eine solche Datenbank mit den folgenden Tabellen erstellt:

1) Tabelle "Spieler", die das Wesen des Spielers beschreibt:

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

Füllte es mit folgenden Daten:



2) Tabelle "Scores", die eingeführt wird, um den Normalisierungsgrad der Datenbank zu erhöhen

 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") ); 

Füllte es mit folgenden Daten:



Bibliotheken verbinden


Wir erstellen eine Datenbank in den Assets / StreamingAssets unseres Projekts (ich habe db.bytes), dann müssen wir die Bibliotheken verbinden, um mit dieser Datenbank arbeiten zu können. Laden Sie die Datei sqlite3.dll von der offiziellen Website herunter, um mit SQLite unter Windows zu arbeiten. Ich habe ein paar Tage gebraucht, um diese ACBD-Freunde mit Android zu finden, da sich herausstellte, dass die in diesem Artikel angegebene Bibliothek nicht funktioniert. Ich persönlich habe es nicht geschafft, mit Android zu arbeiten. Die Fehler sind ständig gestiegen. Dafür habe ich diese hochgeladen, die irgendwo im Internet gefunden wurden Version der Bibliothek für Android. Wir platzieren die Bibliotheken hier - Assets / Plugins / sqlite.dll und Assets / Plugins / Android / sqlite.so .

Kopieren Sie nach all diesen Manipulationen System.Data.dll und Mono.Data.Sqlite.dll aus C: \ Programme (x86) \ Unity \ Editor \ Data \ Mono \ lib \ mono \ 2.0 und fügen Sie die Assets / Plugins Ihres Unity-Projekts ein. Ich möchte darauf hinweisen, dass Unity in der Version 2018 möglicherweise schreibt, dass System.Data.dll bereits verbunden ist und ein Konflikt zwischen zwei identischen Dateien besteht. Eigentlich ist dies einfach gelöst, wir löschen die neu eingefügte System.Data.dll nicht .

Die Struktur der Bibliotheken sollte wie folgt sein:

Assets / Plugins / Mono.Data.Sqlite.dll - nur benötigt :)
Assets / Plugins / System.Data.dll - ähnlicher Grund
Assets / Plugins / sqlite3.dll - für die Arbeit mit SQLite unter Windows
Assets / Plugins / Android / libsqlite3.so - für die Arbeit mit SQLite unter Android

Schreiben eines Skripts für die Arbeit mit der Datenbank


Und schließlich können wir ein Skript schreiben, um mit der erstellten Datenbank zu arbeiten. Erstellen Sie zunächst eine MyDataBase-Datei und verbinden Sie die Bibliotheken System.Data , Mono.Data.Sqlite und System.IO , machen Sie die MyDataBase-Klasse statisch und entfernen Sie natürlich die Vererbung von MonoBehaviour. Fügen Sie 3 private Variablen und eine Konstante mit dem Namen der Datenbankdatei hinzu. Wir sollten so etwas bekommen:

 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; } 

Das ist natürlich alles gut, aber wir können nicht mit der Datenbank arbeiten. Um mit der Datenbank arbeiten zu können, müssen wir den Pfad dazu ermitteln. Ich schlage vor, einen statischen Konstruktor zu erstellen, der nur den Pfad zur Datenbank abruft (ich erinnere mich, dass die Datenbank in StreamingAssets liegt).

 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); } 

Hinweis Wir müssen die Datenbank in den angegebenen Pfaden entpacken ( Application.dataPath / db.bytes für Windows und Application.persistentDataPath / db.bytes für Android), da der Ordner StreamingAssets nach dem Zusammenbau das ReadOnly-Attribut hat (außer für Android) und wir nichts schreiben können dann in der Datenbank. Um etwas in die Datenbank schreiben zu können, entpacken wir unsere Datenbank. In diesem Artikel wird detailliert angegeben, welche Pfade und unter welcher Plattform verwendet werden sollen.

Wir werden Methoden zum Öffnen und Schließen einer Verbindung sowie eine Methode schreiben, die eine Anforderung ausführt, für die keine Rückgabewerte erforderlich sind, z. B. 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(); } 

Wie durch ein Wunder kann unser Skript jetzt Anforderungen zur Datenänderung ausführen. Aber was ist mit einem sehr wichtigen SELECT? Ich habe beschlossen, dass der Rückgabewert der Methode, die die Abfrage zur Datenauswahl ausführen soll, vom Typ DataTable oder der Zeichenfolge ist, wenn Sie 1 Wert erhalten möchten. Schreiben Sie dazu 2 Methoden:

 /// <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]; } 

Fertig, jetzt haben wir ein einfaches Skript, das Anfragen zur Datenänderung und -auswahl stellen kann. Schreiben wir jetzt das ScoreManager-Skript. Daraufhin wird eine Tabelle mit den besten Ergebnissen in absteigender Reihenfolge sortiert. Zeigen Sie zur Überprüfung den Spitznamen des Anführers und seine Punkte in Debug.Log an.

 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()} ."); } } 

Folgendes erhalten wir beim Start:



Vielen Dank für Ihre Aufmerksamkeit, ich nehme gerne konstruktive Kritik entgegen.

Source: https://habr.com/ru/post/de442954/


All Articles