Usando SQLite no Unity (Unity + SQLite)

Olá a todos, este post se concentrará em trabalhar com o Banco de Dados Relacional Embutido SQLite da Unity. Este artigo foi escrito por um iniciante para iniciantes com o objetivo de mostrar como trabalhar com o SQLite, pressupõe-se que você conheça os conceitos básicos do SQL. Como não há um tutorial claro para iniciantes na Internet, decidi ocupar esse nicho. Neste artigo, escreveremos uma classe simples para trabalhar com este DBMS, que pode ser usada para resolver uma grande variedade de tarefas (localização, armazenamento de dados, manutenção de tabelas diferentes).

O que é SQLite e por que precisamos dele?


O SQLite é um sistema de gerenciamento de banco de dados relacional incorporado compacto bastante popular. Uma vantagem importante do SQLite é sua plataforma cruzada, para que possamos usar o SQLite para várias plataformas. O SQLite pode ser usado quando a velocidade e a compactação são necessárias, portanto, no caso de um problema de armazenamento de dados, decidi resolvê-lo usando este DBMS.

Como trabalhar com SQLite?


Para criar e editar nosso banco de dados, há um grande número de utilitários e plug-ins gratuitos para navegadores, eu pessoalmente utilizarei o DB Browser (SQLite), ele me enganchou com sua simplicidade e me pareceu não muito conveniente trabalhar com vários plug-ins no navegador. Em geral, quem quiser, funciona assim. Usando o DB Browser, você pode facilmente criar tabelas, estabelecer conexões entre elas e preenchê-las com dados sem recorrer ao SQL. Além disso, no DB Browser, você pode fazer tudo com canetas usando SQLite, então aqui é mais conveniente para alguém.

Crie e preencha um banco de dados de teste


Criamos um banco de dados no Assets / StreamingAssets do nosso projeto (eu tenho db.bytes, já que o Unity entende apenas * .bytes para bancos de dados, usaremos essa extensão). Puramente, por exemplo, criei esse banco de dados com as seguintes tabelas:

1) Tabela "Jogador", que descreve a essência do jogador:

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

Preencha com os seguintes dados:



2) Tabela "Pontuações", introduzida para aumentar o nível de normalização do banco de dados

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

Preencha com os seguintes dados:



Conectando bibliotecas


Criamos um banco de dados no Assets / StreamingAssets do nosso projeto (eu tenho db.bytes), então precisamos conectar as bibliotecas para trabalhar com esse banco de dados. Faça o download do arquivo sqlite3.dll no site oficial para trabalhar com SQLite no Windows. Demorei alguns dias para fazer com que essa ACBD fizesse amizade com o Android, já que a biblioteca indicada neste artigo não estava funcionando, eu pessoalmente não consegui trabalhar com ela no Android, os erros aumentavam constantemente, para isso eu carreguei isso encontrado em algum lugar da Internet versão da biblioteca para Android. Colocamos as bibliotecas aqui - Assets / Plugins / sqlite.dll e Assets / Plugins / Android / sqlite.so .

Após todas essas manipulações, copie System.Data.dll e Mono.Data.Sqlite.dll de C: \ Arquivos de programas (x86) \ Unity \ Editor \ Data \ Mono \ lib \ mono \ 2.0 e cole os ativos / plug-ins do seu projeto do Unity. Quero observar que, na versão 2018, o Unity pode escrever que o System.Data.dll já está conectado e há um conflito de dois arquivos idênticos. Na verdade, isso é resolvido simplesmente, não excluímos o System.Data.dll recentemente inserido.

A estrutura das bibliotecas deve ser a seguinte:

Ativos / Plugins / Mono.Data.Sqlite.dll - apenas necessário :)
Assets / Plugins / System.Data.dll - motivo semelhante
Ativos / Plugins / sqlite3.dll - para trabalhar com SQLite no Windows
Recursos / Plugins / Android / libsqlite3.so - para trabalhar com SQLite no Android

Escrevendo um script para trabalhar com o banco de dados


E, finalmente, podemos começar a escrever um script para trabalhar com o banco de dados criado. Primeiro, crie um arquivo MyDataBase e conecte as bibliotecas System.Data , Mono.Data.Sqlite , System.IO , torne a classe MyDataBase estática e, é claro, remova a herança do MonoBehaviour. Adicione 3 variáveis ​​privadas e uma constante com o nome do arquivo de banco de dados. Deveríamos ter algo assim:

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

Tudo isso é bom, é claro, mas não poderemos trabalhar com o banco de dados. Para trabalhar com o banco de dados, precisamos encontrar o caminho para ele, proponho a criação de um construtor estático, que apenas obterá o caminho para o banco de dados (lembro que o banco de dados está no 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); } 

Nota Precisamos descompactar o banco de dados nos caminhos especificados ( Application.dataPath / db.bytes para Windows e Application.persistentDataPath / db.bytes para Android), pois a pasta StreamingAssets, após a montagem, possui o atributo ReadOnly (exceto Android) e não podemos escrever nada depois no banco de dados. Na verdade, para poder escrever algo no banco de dados, descompactamos nosso banco de dados. É dito em detalhes quais caminhos, sob qual plataforma usar neste artigo .

Escreveremos métodos para abrir uma conexão e fechar, bem como um método que executará uma solicitação que não exija retorno de valores, por exemplo, 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(); } 

Milagrosamente, agora nosso script pode executar solicitações de modificação de dados. Mas e um SELECT muito importante? Decidi que o valor de retorno do método que deve executar a consulta para seleção de dados deve ser do tipo ou cadeia de caracteres DataTable, se você deseja obter 1 valor. Para fazer isso, escreva 2 métodos:

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

Concluído, agora temos um script simples que pode fazer solicitações de modificação e seleção de dados. Vamos escrever o script ScoreManager agora. Que receberá uma tabela com os melhores resultados classificados em ordem decrescente. E, para verificação, exiba o apelido do líder e seus pontos em 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()} ."); } } 

Aqui está o que obtemos na inicialização:



Obrigado por sua atenção, terei prazer em aceitar críticas construtivas.

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


All Articles