Utilisation de SQLite dans Unity (Unity + SQLite)

Bonjour à tous, cet article se concentrera sur l'utilisation de la base de données relationnelle intégrée SQLite d'Unity. Cet article a été écrit par un novice pour débutants dans le but de vous montrer comment travailler avec SQLite, on suppose que vous connaissez les bases de SQL. Puisqu'il n'y a pas de tutoriel clair pour les débutants sur Internet, j'ai décidé d'occuper ce créneau. Dans cet article, nous allons écrire une classe simple pour travailler avec ce SGBD, qui peut être utilisée pour résoudre un large éventail de problèmes (localisation, stockage de données, maintenance de différentes tables).

Qu'est-ce que SQLite et pourquoi en avons-nous besoin?


SQLite est un système compact de gestion de base de données relationnelle embarquée qui est assez populaire. Un avantage important de SQLite est sa multiplateforme, nous pouvons donc utiliser SQLite pour diverses plates-formes. SQLite peut être utilisé lorsque la vitesse et la compacité sont nécessaires, par conséquent, en cas de problème de stockage de données, j'ai décidé de le résoudre en utilisant ce SGBD.

Comment travailler avec SQLite?


Pour créer et éditer notre base de données, il existe un grand nombre d'utilitaires et de plug-ins gratuits pour les navigateurs.J'utiliserai personnellement DB Browser (SQLite), cela m'a accroché avec sa simplicité et il ne m'a pas semblé très pratique de travailler avec divers plug-ins dans le navigateur. En général, celui qui le veut fonctionne comme ça. À l'aide de DB Browser, vous pouvez facilement créer des tableaux, établir des connexions entre eux et les remplir de données sans recourir à SQL. De plus, dans DB Browser, vous pouvez tout faire avec des stylets à l'aide de SQLite, alors ici, c'est plus pratique pour quelqu'un.

Créer et remplir une base de données de test


Nous créons une base de données dans les Assets / StreamingAssets de notre projet (je l'ai en db.bytes, car Unity ne comprend que * .bytes pour les bases de données, nous utiliserons cette extension). Par exemple, j'ai créé une telle base de données avec les tableaux suivants:

1) Tableau "Joueur", qui décrit l'essence du joueur:

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

Rempli avec les données suivantes:



2) Tableau "Scores", qui est introduit pour augmenter le niveau de normalisation de la base de données

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

Rempli avec les données suivantes:



Connexion des bibliothèques


Nous créons une base de données dans les actifs / StreamingAssets de notre projet (j'ai db.bytes), puis nous devons connecter les bibliothèques pour travailler avec cette base de données. Téléchargez le fichier sqlite3.dll sur le site officiel pour travailler avec SQLite sous Windows. Cela m'a pris quelques jours pour me faire des amis de l'ACBD avec Android, car la bibliothèque indiquée dans cet article s'est avérée ne pas fonctionner, personnellement je n'ai pas réussi à travailler avec elle sur Android, les erreurs ont constamment grimpé, pour cela je télécharge ceci trouvé quelque part sur Internet version de la bibliothèque pour Android. Nous plaçons les bibliothèques ici - Assets / Plugins / sqlite.dll et Assets / Plugins / Android / sqlite.so .

Après toutes ces manipulations, copiez System.Data.dll et Mono.Data.Sqlite.dll à partir de C: \ Program Files (x86) \ Unity \ Editor \ Data \ Mono \ lib \ mono \ 2.0 et collez les actifs / plugins de votre projet Unity. Je veux noter que dans la version 2018, Unity peut écrire que System.Data.dll est déjà connecté et qu'il y a un conflit de deux fichiers identiques. En fait, cela est résolu simplement, nous ne supprimons pas le System.Data.dll nouvellement inséré.

La structure des bibliothèques doit être la suivante:

Assets / Plugins / Mono.Data.Sqlite.dll - juste nécessaire :)
Assets / Plugins / System.Data.dll - raison similaire
Assets / Plugins / sqlite3.dll - pour travailler avec SQLite sous Windows
Actifs / Plugins / Android / libsqlite3.so - pour travailler avec SQLite sur Android

Écrire un script pour travailler avec la base de données


Et enfin, nous pouvons commencer à écrire un script pour travailler avec la base de données créée. Tout d'abord, créez un fichier MyDataBase et connectez les bibliothèques System.Data , Mono.Data.Sqlite , System.IO , rendez la classe MyDataBase statique et, bien sûr, supprimez l'héritage de MonoBehaviour. Ajoutez 3 variables privées et une constante avec le nom du fichier de base de données. Nous devrions obtenir quelque chose comme ça:

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

C'est très bien, bien sûr, mais nous ne pourrons pas travailler avec la base de données. Pour travailler avec la base de données, nous devons obtenir le chemin d'accès, je propose de créer un constructeur statique, qui obtiendra simplement le chemin d'accès à la base de données (je me souviens que la base de données se trouve dans 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); } 

Remarque Nous devons décompresser la base de données dans les chemins spécifiés ( Application.dataPath / db.bytes pour Windows et Application.persistentDataPath / db.bytes pour Android) car le dossier StreamingAssets, après assemblage, a l'attribut ReadOnly (sauf pour Android) et nous ne pourrons rien écrire puis dans la base de données. En fait, afin de pouvoir écrire quelque chose dans la base de données, nous déballons notre base de données. Il est dit en détail quels chemins, sous quelle plateforme utiliser dans cet article .

Nous allons écrire des méthodes pour ouvrir et fermer une connexion, ainsi qu'une méthode qui exécutera une demande qui ne nécessite pas de retour de valeurs, par exemple 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(); } 

Miraculeusement, notre script peut désormais exécuter des demandes de modification de données. Mais qu'en est-il d'un SELECT très important? J'ai décidé que la valeur de retour de la méthode qui devrait exécuter la requête pour la sélection des données devrait être du type ou de la chaîne DataTable, si vous voulez obtenir 1 valeur. Pour ce faire, écrivez 2 méthodes:

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

Terminé, nous avons maintenant un script simple qui peut faire des demandes de modification et de sélection de données. Écrivons maintenant le script ScoreManager. Qui recevra un tableau des meilleurs résultats triés par ordre décroissant. Et, pour vérification, affichez le surnom du leader et ses points dans 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()} ."); } } 

Voici ce que nous obtenons au démarrage:



Merci de votre attention, j'accepterai volontiers des critiques constructives.

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


All Articles