6

Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二)

 3 years ago
source link: https://www.xuanyusong.com/archives/1454
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
首页 > Unity3D频道 > 【Unity3D研究院之游戏开发】 > Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二)

Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二)

如果大家对Unity中如何使用数据库还不是很了解那么请看我之前的这篇文章。Unity3D研究院之使用C#语言建立本地数据库(二十三)本篇文章我们讨论如何在Unity中打开一个第三方数据库配合Android与编辑器进行同步开发。如下图所示,这个是我目前工程的结构,为了方便调试MOMO使用预定义标签将编辑器与Android平台区分开,方便编辑器与Android平台同时调试。

下图如果看的不清楚,点击图片可查看大图。 不仅在Unity编辑器中可以显示数据库读取的内容,直接编译在真机中也可以显示数据库读取的内容。

Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二) - 雨松MOMO程序研究院 - 1

按照上图所示我们把第三方数据库放在Plugins->Android->assets中,切记必须放在这里,否无无效,然后是代码。这个第三方数据库是MOMO以前做测试一个号码归属地的时候制作的。所以数据库的内容还是比较大的,蛤蛤。

DbAccess.cs

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

然后是Test.cs直接把它挂在摄像机对象身上。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Mono.Data.Sqlite;
public class Test  :MonoBehaviour
//这三个是从数据库中取得的字段内容
string  number = "null";
string  city= "null";
string  location = "null";
//处理在Android中显示中文
public GUISkin skin;
void Start ()
loadSQL ();
void loadSQL ()
//如果运行在编辑器中
#if UNITY_EDITOR
//通过路径找到第三方数据库
string appDBPath = Application.dataPath + "/Plugins/Android/assets/" + "location.db";
DbAccess db = new DbAccess("URI=file:" + appDBPath);
//如果运行在Android设备中
#elif UNITY_ANDROID
//将第三方数据库拷贝至Android可找到的地方
string appDBPath = Application.persistentDataPath + "/" + "location.db";
//如果已知路径没有地方放数据库,那么我们从Unity中拷贝
if(!File.Exists(appDBPath))
//用www先从Unity中下载到数据库
    WWW loadDB = new WWW("jar:file://" + Application.dataPath + "!/assets/" + "location.db");
//拷贝至规定的地方
    File.WriteAllBytes(appDBPath, loadDB.bytes);
//在这里重新得到db对象。
DbAccess db = new DbAccess("URI=file:" + appDBPath);
#endif
using (SqliteDataReader sqReader = db.SelectWhere("location_date",new string[]{"number","city","location"},new string[]{"_id"},new string[]{"="},new string[]{"25"}))
while (sqReader.Read())
       //从数据库中找到对应字段
  number =  sqReader.GetString(sqReader.GetOrdinal("number"));
  city =  sqReader.GetString(sqReader.GetOrdinal("city"));
  location = sqReader.GetString(sqReader.GetOrdinal("location")) ;
Debug.Log("number =" + number + " city =" + city + " location =" + location );
sqReader.Close();
db.CloseSqlConnection();
void OnGUI()
GUI.skin = skin;
GUILayout.Box("number =" + number);
GUILayout.Box("city =" + city);
GUILayout.Box("location =" + location);

上面代码中我们使用到了预定于标签,用于编译时区分游戏平台与版本。这么一来我们既可以在编辑器中操作数据库也可以在Android中操作数据库一举两得,主要是是Android平台比较特殊,不能从Unity的Assets资源路径中读取二进制文件。说道二进制文件,这里不仅读取第三方数据库还可以读取其它文件,二进制文件都可以读取,比如文本文件、图片、资源等等。

需要注意的是你得把你的二进制文件放在Plugins->Android->assets中,然后根据下面的路径就可以在Android中读取。

string Path  = jar:file://” + Application.dataPath + “!/assets/” + “你的文件“;

另外,使用这种方法读取地方放数据库后,是可以继续向数据库执行插入、删除、修改 、查询、等操作,用起来还是比较方便的。

Unity预定义标签的种类还有很多,不仅可以区分平台还可以区分版本。

UNITY_EDITOR Define for calling Unity Editor scripts from your game code. UNITY_STANDALONE_OSX Platform define for compiling/executing code specifically for Mac OS (This includes Universal, PPC and Intel architectures). UNITY_DASHBOARD_WIDGET Platform define when creating code for Mac OS dashboard widgets. UNITY_STANDALONE_WIN Use this when you want to compile/execute code for Windows stand alone applications. UNITY_WEBPLAYER Platform define for web player content (this includes Windows and Mac Web player executables). UNITY_WII Platform define for compiling/executing code for the Wii console. UNITY_IPHONE Platform define for compiling/executing code for the iPhone platform. UNITY_ANDROID Platform define for the Android platform. UNITY_PS3 Platform define for running PlayStation 3 code. UNITY_XBOX360 Platform define for executing Xbox 360 code. UNITY_NACL Platform define when compiling code for Google native client (this will be set additionally to UNITY_WEBPLAYER). UNITY_FLASH Platform define when compiling code for Adobe Flash.

Note: These defines were introduced at version 3.0.

Also you can compile code selectively depending on the version of the engine you are working on. Currently the supported ones are:

UNITY_2_6 Platform define for the major version of Unity 2.6. UNITY_2_6_1 Platform define for specific version 1 from the major release 2.6. UNITY_3_0 Platform define for the major version of Unity 3.0. UNITY_3_0_0 Platform define for the specific version 0 of Unity 3.0. UNITY_3_1 Platform define for major version of Unity 3.1. UNITY_3_2 Platform define for major version of Unity 3.2. UNITY_3_3 Platform define for major version of Unity 3.3. UNITY_3_4 Platform define for major version of Unity 3.4. UNITY_3_5 Platform define for major version of Unity 3.5. 

 详细内容可以查看官网http://docs.unity3d.com/Documentation/Manual/PlatformDependentCompilation.html

用法就不解释了,地球人都知道。

雨松MOMO希望和大家一起进步,加油~~~最后文本的源码下载:http://vdisk.weibo.com/s/ac3xI

雨松MOMO祝大家学习愉快,哇咔咔,晚安啦啦啦~~

作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二)》有 65 条评论

  1. ?s=80罗展途 说:

    一直说没有libsqlite.so,可实际上是有的啊

  2. ?s=80罗展途 说:

    是不是还要什么权限啊,我已经走到Open了,报错dbConnection.Open ();啊

  3. bbd596a4c6206f2275ebbec559fca058?s=80洋洋 说:

    手机上已经不行了,移过来的数据库没有内容,而且还不能创建表格,加入数据,不知道要怎么搞啊

  4. ?s=80艾戈塔特 说:

    在安卓上数据库读取成功了但是写入信息失败了,求解

    • ?s=80paradise_wu 说:

      你好,请问你使用的是什么方法读取到的,能分享下吗?我能在Application.persistentDataPath文件夹下找到该文件,但是不能使用协程加载也不能读取数据

  5. ?s=80贾磊 说:

    数据库文件 一旦连接 导致文件被占用 无法被删除 求解

  6. ?s=8090 说:

    博主,请问下libsqlite3.so文件是怎么生成的?我试了下如果没有这个文件,安卓上是无法正常运行的。

  7. ?s=80蓝小野 说:

    UNITY_STANDALONE_WIN 和 UNITY_STANDALONE_OSX 没说呀,该怎么处理

  8. using (SqliteDataReader reader = db.SelectWhere(“iseetable”, new string[] { “name”, “email”, “qq” }, new string[] { “name” }, new string[] { “like” }, new string[] { “%姣%” }))我把你的代码改成你这个模糊查询了,然后我就凌乱了string[] name = new string[]{};这个定义改为数组 List temp = new List(); for (int i = 0; i < temp.Count; i) { GUI.skin = skin; GUILayout.Box(“name=” name Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二) - 雨松MOMO程序研究院 - 1 ” “); GUILayout.Box(“qq=” qq Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二) - 雨松MOMO程序研究院 - 2 ” “); GUILayout.Box(“email=” email Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二) - 雨松MOMO程序研究院 - 3 ); }显示也改为数组可是。。 name = reader.GetString(reader.GetOrdinal(“name”));这个报错 不知道怎么改 求指导我是新手大神

  9. using (SqliteDataReader reader = db.SelectWhere(“iseetable”, new string[] { “name”, “email”, “qq” }, new string[] { “name” }, new string[] { “like” }, new string[] { “%姣%” }))我把你的代码改成你这个模糊查询了,然后我就凌乱了string[] name = new string[]{};这个定义改为数组 List temp = new List(); for (int i = 0; i < temp.Count; ++i) { GUI.skin = skin; GUILayout.Box(“name=” + name Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二) - 雨松MOMO程序研究院 - 1 +” “); GUILayout.Box(“qq=” + qq Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二) - 雨松MOMO程序研究院 - 2 +” “); GUILayout.Box(“email=” + email Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二) - 雨松MOMO程序研究院 - 3 ); }显示也改为数组可是。。 name = reader.GetString(reader.GetOrdinal(“name”));这个报错 不知道怎么改 求指导我是新手大神

  10. ?s=80高山流水 说:

    松哥,我也遇到了同样的问题,在编辑器里可以但是在真机中不行,求解决啊

  11. ?s=80高山流水 说:

    大神,我的也倒不出来.apk包,报错为Error building Player: Exception: apk (invokation failed)ERROR: Duplicate file(s) in apk: ‘E:scTempStagingArearaw.ap_’cmd:apk E:scTemp/StagingArea/Package_unaligned.apk -z E:scTemp/StagingArea/assets.ap_ -z E:scTemp/StagingArea/bin/resources.ap_ -nf E:scTemp/StagingArea/libs -f E:scTemp/StagingArea/bin/classes.dex -v -z E:scTemp/StagingArea/raw.ap_stdout;stderr:ERROR: Duplicate file(s) in apk: ‘E:scTempStagingArearaw.ap_’怎么处理一下呢?谢谢松哥~

  12. ?s=80 说:

    我是直接下的MOMO提供的原文做实验的,在PC没问题, ,真机读不出数据。怎么回事能呢,MOMO能给些提示吗

  13. ?s=80 说:

    我也是在PC没问题,直接编辑android ,真机读不出数据。怎么回事能呢,MOMO能给些提示吗

  14. ?s=80任博学 说:

    大家都说android真机出现问题,为什么这个项目我在Unity中直接打包android的apk都不行呢?提示如下三个错误,1,!IsDirectoryCreated(kManagedDllsFolder)UnityEditor.HostView:OnGUI()2,BadImageFormatException: Format of the executable (.exe) or library (.dll) is invalid.Mono.Cecil.PE.ImageReader.ReadImage ()Mono.Cecil.PE.ImageReader.ReadImageFrom (System.IO.Stream stream)Mono.Cecil.ModuleDefinition.ReadModule (System.IO.Stream stream, Mono.Cecil.ReaderParameters parameters)Mono.Cecil.ModuleDefinition.ReadModule (System.String fileName, Mono.Cecil.ReaderParameters parameters)Mono.Cecil.ModuleDefinition.ReadModule (System.String fileName)Mono.Cecil.AssemblyDefinition.ReadAssembly (System.String fileName)UnityEditor.AssemblyReferenceChecker.CollectReferences (System.String path, Boolean withMethods, Single progressValue, Boolean ignoreSystemDlls)UnityEditor.AssemblyReferenceChecker.GetScriptsHaveMouseEvents (System.String path)3,Error building Player: IOException: Failed to Copy File / Directory from ‘/Applications/Unity/Unity.app/Contents/PlaybackEngines/AndroidDevelopmentPlayer/Data/unity default resources’ to ‘Temp/StagingArea/Data/unity default resources’.请问有没有人知道什么原因呢?开发平台Mac,Unity版本4.2.0f4

  15. f5a979bcec2ecddf47059583066991cf?s=80ESIANG 说:

    我也是在PC没问题,直接编辑android ,真机读不出数据。头大 Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二) - 雨松MOMO程序研究院 - 1

  16. ?s=80英璐铮 说:

    松哥啊,我在PC上的时候没有问题,但是只要是在安卓上查询不出数据,感觉应该是只要有 数据库操作 的地方都被自动跳过或者忽视了……应该是什么问题呢?

  17. ?s=80七月初七 说:

    请问 libsqlite3.so这个文件,是你build之前就放进去的,还是build之后产生的?我这边 android环境下无论怎样,也读不出数据,Unity版本用的4,1.0

  18. 9dea4e7e1b161dd2820fd04b1e2cdf0c?s=80田大爷 说:

    为什么我在安卓上导不出啊?

  19. 07a38511163cb6e576ea881c3505367b?s=80yx8728 说:

    4.1.2测试失败,后把db放到StreamingAssets下面搞定

        • ?s=80七月初七 说:

          请问怎么解决的,哪几个dll文件,我这边Mono.Data.dll.System.Data,Mono.Data.Sqlite.dll,libsqlite3.so,sqlite3.dll,都齐了,还是不行,下了你链接里的到处包,我这边还是在android里读不出数据。。

          • 3fc984de71a64dce933d10f8631dc24a?s=80wjh 说:

            现在用Unity4.5后 数据库又读不出来了。Android平台测试 ,找得到db文件,但无法读取。如果是用代码在Android平台创建数据库,插入数据,读取,是可以读的。

          • 3fc984de71a64dce933d10f8631dc24a?s=80wjh 说:

            做了点改动,加载不了主要是因为www加载有一定时间,还没加载完时调用File.WriteAllBytes(appDBPath, loadDB.bytes);会导致数据库读不出来。这个方法建议在封装成协同函数。if(!File.Exists(appDBPath)) { log += “xys–“; //用www先从Unity中下载到数据库 WWW loadDB = new WWW(“jar:file://” + Application.dataPath + “!/assets/” + “location.db”); bool boo = true; while(boo) { if(loadDB.isDone) { copyPath += “jar:file://” + Application.dataPath + “!/assets/” + “location.db”; //拷贝至规定的地方 File.WriteAllBytes(appDBPath, loadDB.bytes); copySuccess += ” xuanyusong no db “; boo = false; log += “xysCopyFinish–“; } yield return new WaitForSeconds(0.3f); log += ” 0.3–“; } }

          • ?s=80wjh 说:

            做了点改动,加载不了主要是因为www加载有一定时间,还没加载完时调用File.WriteAllBytes(appDBPath, loadDB.bytes);会导致数据库读不出来。这个方法建议在封装成协同函数。if(!File.Exists(appDBPath)) { log = “xys–“;//用www先从Unity中下载到数据库 WWW loadDB = new WWW(“jar:file://” Application.dataPath “!/assets/” “location.db”); bool boo = true; while(boo) { if(loadDB.isDone) { copyPath = “jar:file://” Application.dataPath “!/assets/” “location.db”; //拷贝至规定的地方 File.WriteAllBytes(appDBPath, loadDB.bytes); copySuccess = ” xuanyusong no db “; boo = false; log = “xysCopyFinish–“; } yield return new WaitForSeconds(0.3f); log = ” 0.3–“; }}

  20. ?s=80吴捷宏 说:

    大神 我新增加了 LAST_INSERT_ROWID() 但是不知道为什么报错了 测试用的Unitypackage已经发大神邮箱了 求帮忙呀

  21. ?s=80若水秋荷 说:

    松哥,请问下如何用unity3d读取Android手机上的GPS和陀螺仪的信息,如何实现呢?

  22. ?s=80郭袁.unity 说:

    请问unity中插入有米广告流程是怎么样的? 我一直搞一直提示错误的。

  23. 62b44485b2bf475afa1307e9c0cb6b5a?s=80海鹏 说:

    您好,我最近正在弄关于android与unity之间的信息传递,遇到个问题能帮忙解答下吗?
    UnityPlayer.UnitySendMessage(“Main Camera”,”messgae”,s);
    我在android端调用这个方法,可以实现string类型的传递,可是如果我想传递的是byte数组,应该怎么操作呢?

  24. 997b4c2d7733edbbff292bf8881c6e2d?s=80感谢MOMO 说:

    学习了, 感谢MOMO的分享!

留下一个回复 取消回复

你的email不会被公开。

评论

姓名 *

电子邮件 *

站点


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK