声明:本文主要参考 雨松momo 的文章(十分感谢),但是在android设备上运行时,出现了不能操作数据库的问题;原文链接:http://www.xuanyusong.com/archives/831 http://www.xuanyusong.com/archives/1454
本篇文章我们讨论如何在Unity中打开一个第三方数据库配合Android与编辑器进行同步开发。
一. 怎么让手机使用sqlite3数据库
1. 需要的文件如下:
2.存放路径:
在Assets目录下新建Plugins,把Mono.Data.dll、Mono.Data.Sqlite.dll、System.Data.dll、sqlite3.dll 放到这层目录下,然后在这层目录下建立Android,再将libsqlite3.so放到Android目录下,最后再在这个Android目录下创建assets目录,然后将.db文件放于此,,我试过各种路径存放和试剥离不需要的dll,都不行。
二. c#接口的脚本
1. 注意:下面脚本不要绑定在任何游戏对象身上,大家无需把它当作脚本可以当作一个工具类来使用。
- using UnityEngine;
- using System;
- using System.Collections;
- using Mono.Data.Sqlite;
- public class DbAccess
- {
- private SqliteConnection dbConnection;
- private SqliteCommand dbCommand;
- private SqliteDataReader reader;
- public DbAccess(string connectionString)
- {
- OpenDB(connectionString);
- }
- public DbAccess()
- {
- }
- public void OpenDB(string connectionString)
- {
- try
- {
- dbConnection = new SqliteConnection(connectionString);
- dbConnection.Open();
- Debug.Log("Connected to db");
- }
- catch (Exception e)
- {
- string temp1 = e.ToString();
- Debug.Log(temp1);
- }
- }
- public void CloseSqlConnection()
- {
- if (dbCommand != null)
- {
- dbCommand.Dispose();
- }
- dbCommand = null;
- if (reader != null)
- {
- reader.Dispose();
- }
- reader = null;
- if (dbConnection != null)
- {
- dbConnection.Close();
- }
- dbConnection = null;
- Debug.Log("Disconnected from db.");
- }
- public SqliteDataReader ExecuteQuery(string sqlQuery)
- {
- dbCommand = dbConnection.CreateCommand();
- dbCommand.CommandText = sqlQuery;
- reader = dbCommand.ExecuteReader();
- return reader;
- }
- public SqliteDataReader ReadFullTable(string tableName)
- {
- string query = "SELECT * FROM " + tableName;
- return ExecuteQuery(query);
- }
- public SqliteDataReader InsertInto(string tableName, string[] values)
- {
- string query = "INSERT INTO " + tableName + " VALUES (" + values[0];
- for (int i = 1; i < values.Length; ++i)
- {
- query += ", " + values[i];
- }
- query += ")";
- return ExecuteQuery(query);
- }
- public SqliteDataReader UpdateInto(string tableName, string[] cols, string[] colsvalues, string selectkey, string selectvalue)
- {
- string query = "UPDATE " + tableName + " SET " + cols[0] + " = " + colsvalues[0];
- for (int i = 1; i < colsvalues.Length; ++i)
- {
- query += ", " + cols[i] + " =" + colsvalues[i];
- }
- query += " WHERE " + selectkey + " = " + selectvalue + " ";
- return ExecuteQuery(query);
- }
- public SqliteDataReader Delete(string tableName, string[] cols, string[] colsvalues)
- {
- string query = "DELETE FROM " + tableName + " WHERE " + cols[0] + " = " + colsvalues[0];
- for (int i = 1; i < colsvalues.Length; ++i)
- {
- query += " or " + cols[i] + " = " + colsvalues[i];
- }
- Debug.Log(query);
- return ExecuteQuery(query);
- }
- public SqliteDataReader InsertIntoSpecific(string tableName, string[] cols, string[] values)
- {
- if (cols.Length != values.Length)
- {
- throw new SqliteException("columns.Length != values.Length");
- }
- string query = "INSERT INTO " + tableName + "(" + cols[0];
- for (int i = 1; i < cols.Length; ++i)
- {
- query += ", " + cols[i];
- }
- query += ") VALUES (" + values[0];
- for (int i = 1; i < values.Length; ++i)
- {
- query += ", " + values[i];
- }
- query += ")";
- return ExecuteQuery(query);
- }
- public SqliteDataReader DeleteContents(string tableName)
- {
- string query = "DELETE FROM " + tableName;
- return ExecuteQuery(query);
- }
- public SqliteDataReader CreateTable(string name, string[] col, string[] colType)
- {
- if (col.Length != colType.Length)
- {
- throw new SqliteException("columns.Length != colType.Length");
- }
- string query = "CREATE TABLE " + name + " (" + col[0] + " " + colType[0];
- for (int i = 1; i < col.Length; ++i)
- {
- query += ", " + col[i] + " " + colType[i];
- }
- query += ")";
- return ExecuteQuery(query);
- }
- public SqliteDataReader SelectWhere(string tableName, string[] items, string[] col, string[] operation, string[] values)
- {
- if (col.Length != operation.Length || operation.Length != values.Length)
- {
- throw new SqliteException("col.Length != operation.Length != values.Length");
- }
- string query = "SELECT " + items[0];
- for (int i = 1; i < items.Length; ++i)
- {
- query += ", " + items[i];
- }
- query += " FROM " + tableName + " WHERE " + col[0] + operation[0] + "'" + values[0] + "' ";
- for (int i = 1; i < col.Length; ++i)
- {
- query += " AND " + col[i] + operation[i] + "'" + values[0] + "' ";
- }
- return ExecuteQuery(query);
- }
- }
using UnityEngine;
using System;
using System.Collections;
using Mono.Data.Sqlite;
public class DbAccess
{
private SqliteConnection dbConnection;
private SqliteCommand dbCommand;
private SqliteDataReader reader;
public DbAccess(string connectionString)
{
OpenDB(connectionString);
}
public DbAccess()
{
}
public void OpenDB(string connectionString)
{
try
{
dbConnection = new SqliteConnection(connectionString);
dbConnection.Open();
Debug.Log("Connected to db");
}
catch (Exception e)
{
string temp1 = e.ToString();
Debug.Log(temp1);
}
}
public void CloseSqlConnection()
{
if (dbCommand != null)
{
dbCommand.Dispose();
}
dbCommand = null;
if (reader != null)
{
reader.Dispose();
}
reader = null;
if (dbConnection != null)
{
dbConnection.Close();
}
dbConnection = null;
Debug.Log("Disconnected from db.");
}
public SqliteDataReader ExecuteQuery(string sqlQuery)
{
dbCommand = dbConnection.CreateCommand();
dbCommand.CommandText = sqlQuery;
reader = dbCommand.ExecuteReader();
return reader;
}
public SqliteDataReader ReadFullTable(string tableName)
{
string query = "SELECT * FROM " + tableName;
return ExecuteQuery(query);
}
public SqliteDataReader InsertInto(string tableName, string[] values)
{
string query = "INSERT INTO " + tableName + " VALUES (" + values[0];
for (int i = 1; i < values.Length; ++i)
{
query += ", " + values[i];
}
query += ")";
return ExecuteQuery(query);
}
public SqliteDataReader UpdateInto(string tableName, string[] cols, string[] colsvalues, string selectkey, string selectvalue)
{
string query = "UPDATE " + tableName + " SET " + cols[0] + " = " + colsvalues[0];
for (int i = 1; i < colsvalues.Length; ++i)
{
query += ", " + cols[i] + " =" + colsvalues[i];
}
query += " WHERE " + selectkey + " = " + selectvalue + " ";
return ExecuteQuery(query);
}
public SqliteDataReader Delete(string tableName, string[] cols, string[] colsvalues)
{
string query = "DELETE FROM " + tableName + " WHERE " + cols[0] + " = " + colsvalues[0];
for (int i = 1; i < colsvalues.Length; ++i)
{
query += " or " + cols[i] + " = " + colsvalues[i];
}
Debug.Log(query);
return ExecuteQuery(query);
}
public SqliteDataReader InsertIntoSpecific(string tableName, string[] cols, string[] values)
{
if (cols.Length != values.Length)
{
throw new SqliteException("columns.Length != values.Length");
}
string query = "INSERT INTO " + tableName + "(" + cols[0];
for (int i = 1; i < cols.Length; ++i)
{
query += ", " + cols[i];
}
query += ") VALUES (" + values[0];
for (int i = 1; i < values.Length; ++i)
{
query += ", " + values[i];
}
query += ")";
return ExecuteQuery(query);
}
public SqliteDataReader DeleteContents(string tableName)
{
string query = "DELETE FROM " + tableName;
return ExecuteQuery(query);
}
public SqliteDataReader CreateTable(string name, string[] col, string[] colType)
{
if (col.Length != colType.Length)
{
throw new SqliteException("columns.Length != colType.Length");
}
string query = "CREATE TABLE " + name + " (" + col[0] + " " + colType[0];
for (int i = 1; i < col.Length; ++i)
{
query += ", " + col[i] + " " + colType[i];
}
query += ")";
return ExecuteQuery(query);
}
public SqliteDataReader SelectWhere(string tableName, string[] items, string[] col, string[] operation, string[] values)
{
if (col.Length != operation.Length || operation.Length != values.Length)
{
throw new SqliteException("col.Length != operation.Length != values.Length");
}
string query = "SELECT " + items[0];
for (int i = 1; i < items.Length; ++i)
{
query += ", " + items[i];
}
query += " FROM " + tableName + " WHERE " + col[0] + operation[0] + "'" + values[0] + "' ";
for (int i = 1; i < col.Length; ++i)
{
query += " AND " + col[i] + operation[i] + "'" + values[0] + "' ";
}
return ExecuteQuery(query);
}
}
2. 我使用的是CreateDB.cs来创建zyc.db
- using UnityEngine;
- using System.Collections;
- using System.IO;
- public class CreateDB : MonoBehaviour {
- // public GameObject objDB;
- private string appDBPath;
- private DbAccess db;
- // Use this for initialization
- void Start () {
- //如果运行在编辑器中
- #if UNITY_EDITOR
- //通过路径找到第三方数据库
- string appDBPath = Application.dataPath + "/Plugins/Android/assets/" + "zyc.db";
- DbAccess db = new DbAccess("URI=file:" + appDBPath);
- //如果运行在Android设备中
- #elif UNITY_ANDROID
- <span style="white-space:pre"> </span>//将第三方数据库拷贝至Android可找到的地方
- <span style="white-space:pre"> </span>string appDBPath = Application.persistentDataPath + "/" + "zyc.db";
- <span style="white-space:pre"> </span>
- //如果已知路径没有地方放数据库,那么我们从Unity中拷贝
- <span style="white-space:pre"> </span>if(!File.Exists(appDBPath))
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>//用www先从Unity中下载到数据库
- <span style="white-space:pre"> </span> WWW loadDB = new WWW("jar:file://" + Application.dataPath + "!/assets/" + "zyc.db");
- while(!loadDB.isDone){}
- <span style="white-space:pre"> </span> //拷贝至规定的地方
- <span style="white-space:pre"> </span> File.WriteAllBytes(appDBPath, loadDB.bytes);<span style="white-space:pre"> </span>
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>//在这里重新得到db对象。
- <span style="white-space:pre"> </span>DbAccess db = new DbAccess("URI=file:" + appDBPath);
- #endif
- db.CreateTable("card", new string[] { "id_name", "an_name", "bk_name" }, new string[] { "text", "text", "text" });
- db.InsertInto("card", new string[] { "'1'", "'大象'", "'zyc1'" });
- db.InsertInto("card", new string[] { "'2'", "'狗 '", "'zyc2'" });
- db.InsertInto("card", new string[] { "'3'", "'猫 '", "'zyc3'" });
- db.InsertInto("card", new string[] { "'4'", "'老鼠'", "'zyc'" });
- db.InsertInto("card", new string[] { "'5'", "'猴子'", "'zyc'" });
- db.InsertInto("card", new string[] { "'6'", "'狐狸'", "'zyc'" });
- db.InsertInto("card", new string[] { "'7'", "'熊 '", "'zyc'" });
- db.InsertInto("card", new string[] { "'8'", "'山羊'", "'zyc'" });
- db.InsertInto("card", new string[] { "'9'", "'驴 '", "'zyc'" });
- db.InsertInto("card", new string[] { "'10'", "'马 '", "'zyc'" });
- db.InsertInto("card", new string[] { "'11'", "'骆驼'", "'zyc'" });
- db.InsertInto("card", new string[] { "'12'", "'企鹅'", "'zyc'" });
- db.InsertInto("card", new string[] { "'13'", "'鸟 '", "'zyc'" });
- db.InsertInto("card", new string[] { "'14'", "'长颈鹿'", "'zyc'" });
- db.InsertInto("card", new string[] { "'15'", "'斑马'", "'zyc'" });
- db.InsertInto("card", new string[] { "'16'", "'老虎'", "'zyc'" });
- db.InsertInto("card", new string[] { "'17'", "'狮子'", "'zyc'" });
- db.InsertInto("card", new string[] { "'18'", "'河马'", "'zyc'" });
- db.InsertInto("card", new string[] { "'19'", "'蛇 '", "'zyc'" });
- db.InsertInto("card", new string[] { "'20'", "'龙 '", "'zyc'" });
- // objDB.SetActive(false);
- db.CloseSqlConnection();
- }
- // Update is called once per frame
- void Update () {
- }
- }
using UnityEngine;
using System.Collections;
using System.IO;
public class CreateDB : MonoBehaviour {
// public GameObject objDB;
private string appDBPath;
private DbAccess db;
// Use this for initialization
void Start () {
//如果运行在编辑器中
#if UNITY_EDITOR
//通过路径找到第三方数据库
string appDBPath = Application.dataPath + "/Plugins/Android/assets/" + "zyc.db";
DbAccess db = new DbAccess("URI=file:" + appDBPath);
//如果运行在Android设备中
#elif UNITY_ANDROID
<span style="white-space:pre"> </span>//将第三方数据库拷贝至Android可找到的地方
<span style="white-space:pre"> </span>string appDBPath = Application.persistentDataPath + "/" + "zyc.db";
<span style="white-space:pre"> </span>
//如果已知路径没有地方放数据库,那么我们从Unity中拷贝
<span style="white-space:pre"> </span>if(!File.Exists(appDBPath))
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>//用www先从Unity中下载到数据库
<span style="white-space:pre"> </span> WWW loadDB = new WWW("jar:file://" + Application.dataPath + "!/assets/" + "zyc.db");
while(!loadDB.isDone){}
<span style="white-space:pre"> </span> //拷贝至规定的地方
<span style="white-space:pre"> </span> File.WriteAllBytes(appDBPath, loadDB.bytes);<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>//在这里重新得到db对象。
<span style="white-space:pre"> </span>DbAccess db = new DbAccess("URI=file:" + appDBPath);
#endif
db.CreateTable("card", new string[] { "id_name", "an_name", "bk_name" }, new string[] { "text", "text", "text" });
db.InsertInto("card", new string[] { "'1'", "'大象'", "'zyc1'" });
db.InsertInto("card", new string[] { "'2'", "'狗 '", "'zyc2'" });
db.InsertInto("card", new string[] { "'3'", "'猫 '", "'zyc3'" });
db.InsertInto("card", new string[] { "'4'", "'老鼠'", "'zyc'" });
db.InsertInto("card", new string[] { "'5'", "'猴子'", "'zyc'" });
db.InsertInto("card", new string[] { "'6'", "'狐狸'", "'zyc'" });
db.InsertInto("card", new string[] { "'7'", "'熊 '", "'zyc'" });
db.InsertInto("card", new string[] { "'8'", "'山羊'", "'zyc'" });
db.InsertInto("card", new string[] { "'9'", "'驴 '", "'zyc'" });
db.InsertInto("card", new string[] { "'10'", "'马 '", "'zyc'" });
db.InsertInto("card", new string[] { "'11'", "'骆驼'", "'zyc'" });
db.InsertInto("card", new string[] { "'12'", "'企鹅'", "'zyc'" });
db.InsertInto("card", new string[] { "'13'", "'鸟 '", "'zyc'" });
db.InsertInto("card", new string[] { "'14'", "'长颈鹿'", "'zyc'" });
db.InsertInto("card", new string[] { "'15'", "'斑马'", "'zyc'" });
db.InsertInto("card", new string[] { "'16'", "'老虎'", "'zyc'" });
db.InsertInto("card", new string[] { "'17'", "'狮子'", "'zyc'" });
db.InsertInto("card", new string[] { "'18'", "'河马'", "'zyc'" });
db.InsertInto("card", new string[] { "'19'", "'蛇 '", "'zyc'" });
db.InsertInto("card", new string[] { "'20'", "'龙 '", "'zyc'" });
// objDB.SetActive(false);
db.CloseSqlConnection();
}
// Update is called once per frame
void Update () {
}
}
(1). 上面使用了预定义标签,用于编译时区分游戏平台与版本。
#if UNITY_EDITOR
//如果运行在Android设备中
#elif UNITY_ANDROID
#endif
更多参考:http://docs.unity3d.com/Manual/PlatformDependentCompilation.html
(2). 把二进制文件放在Plugins->Android->assets中,然后根据下面的路径就可以在Android中读取。
string Path = jar:file://” + Application.dataPath + “!/assets/” + “你的文件“;
另外,使用这种方法读取地方放数据库后,是可以继续向数据库执行插入、删除、修改 、查询、等操作,用起来还是比较方便的。
3. Test.cs直接放到Camera上
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using Mono.Data.Sqlite;
- using System.IO;
- using UnityEngine.UI;
- public class Test :MonoBehaviour
- {
- public Text objText;
- private string an_name;
- private string bk_name;
- void Start()
- {
- 数据库文件储存地址
- //string appDBPath = Application.persistentDataPath + "/zyc.db";
- 注意!!!!!!!这行代码的改动
- //DbAccess db = new DbAccess("URI=file:" + appDBPath);
- //如果运行在编辑器中
- #if UNITY_EDITOR
- //通过路径找到第三方数据库
- string appDBPath = Application.dataPath + "/Plugins/Android/assets/" + "zyc.db";
- DbAccess db = new DbAccess("URI=file:" + appDBPath);
- //如果运行在Android设备中
- #elif UNITY_ANDROID
- //将第三方数据库拷贝至Android可找到的地方
- string appDBPath = Application.persistentDataPath + "/" + "zyc.db";
- //如果已知路径没有地方放数据库,那么我们从Unity中拷贝
- if(!File.Exists(appDBPath))
- {
- //用www先从Unity中下载到数据库
- WWW loadDB = new WWW("jar:file://" + Application.dataPath + "!/assets/" + "zyc.db");
- while(!loadDB.isDone){}
- //拷贝至规定的地方
- File.WriteAllBytes(appDBPath, loadDB.bytes);
- }
- //在这里重新得到db对象。
- DbAccess db = new DbAccess("URI=file:" + appDBPath);
- #endif
- //db.CreateTable("PuzzleDebris", new string[] { "_coordinates_number", "_number", "_value" }, new string[] { "text", "text", "text" });
- //db.InsertInto("card", new string[] { "'21'", "'大象'", "'zyc21'" });
- //db.InsertInto("card", new string[] { "'22'", "'狗 '", "'zyc22'" });
- using (SqliteDataReader sqReader = db.SelectWhere("card", new string[]{"an_name","bk_name"}, new string[]{"id_name"}, new string[] {"="}, new string[] {"1"}))
- {
- Debug.Log("Begining Select !!!");
- while (sqReader.Read())
- {
- //目前中文无法显示
- Debug.Log("zyc" + sqReader.GetString(sqReader.GetOrdinal("an_name")));
- Debug.Log("zyc" + sqReader.GetString(sqReader.GetOrdinal("bk_name")));
- an_name = sqReader.GetString(sqReader.GetOrdinal("an_name"));
- bk_name = sqReader.GetString(sqReader.GetOrdinal("bk_name"));
- objText.text = bk_name;
- }
- sqReader.Close();
- db.CloseSqlConnection();
- }
- }
- void Update()
- {
- objText.text = bk_name;
- }
- }
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Mono.Data.Sqlite;
using System.IO;
using UnityEngine.UI;
public class Test :MonoBehaviour
{
public Text objText;
private string an_name;
private string bk_name;
void Start()
{
数据库文件储存地址
//string appDBPath = Application.persistentDataPath + "/zyc.db";
注意!!!!!!!这行代码的改动
//DbAccess db = new DbAccess("URI=file:" + appDBPath);
//如果运行在编辑器中
#if UNITY_EDITOR
//通过路径找到第三方数据库
string appDBPath = Application.dataPath + "/Plugins/Android/assets/" + "zyc.db";
DbAccess db = new DbAccess("URI=file:" + appDBPath);
//如果运行在Android设备中
#elif UNITY_ANDROID
//将第三方数据库拷贝至Android可找到的地方
string appDBPath = Application.persistentDataPath + "/" + "zyc.db";
//如果已知路径没有地方放数据库,那么我们从Unity中拷贝
if(!File.Exists(appDBPath))
{
//用www先从Unity中下载到数据库
WWW loadDB = new WWW("jar:file://" + Application.dataPath + "!/assets/" + "zyc.db");
while(!loadDB.isDone){}
//拷贝至规定的地方
File.WriteAllBytes(appDBPath, loadDB.bytes);
}
//在这里重新得到db对象。
DbAccess db = new DbAccess("URI=file:" + appDBPath);
#endif
//db.CreateTable("PuzzleDebris", new string[] { "_coordinates_number", "_number", "_value" }, new string[] { "text", "text", "text" });
//db.InsertInto("card", new string[] { "'21'", "'大象'", "'zyc21'" });
//db.InsertInto("card", new string[] { "'22'", "'狗 '", "'zyc22'" });
using (SqliteDataReader sqReader = db.SelectWhere("card", new string[]{"an_name","bk_name"}, new string[]{"id_name"}, new string[] {"="}, new string[] {"1"}))
{
Debug.Log("Begining Select !!!");
while (sqReader.Read())
{
//目前中文无法显示
Debug.Log("zyc" + sqReader.GetString(sqReader.GetOrdinal("an_name")));
Debug.Log("zyc" + sqReader.GetString(sqReader.GetOrdinal("bk_name")));
an_name = sqReader.GetString(sqReader.GetOrdinal("an_name"));
bk_name = sqReader.GetString(sqReader.GetOrdinal("bk_name"));
objText.text = bk_name;
}
sqReader.Close();
db.CloseSqlConnection();
}
}
void Update()
{
objText.text = bk_name;
}
}