首页 >Unity3D频道 >【Unity3D研究院之游戏开发】 > Unity3D研究院之在Unity中打开第三方数据库配合Android开发(三十二)
2012
07-05

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)

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

    }

}

 

然后是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_EDITORDefine for calling Unity Editor scripts from your game code.
UNITY_STANDALONE_OSXPlatform define for compiling/executing code specifically for Mac OS (This includes Universal, PPC and Intel architectures).
UNITY_DASHBOARD_WIDGETPlatform define when creating code for Mac OS dashboard widgets.
UNITY_STANDALONE_WINUse this when you want to compile/execute code for Windows stand alone applications.
UNITY_WEBPLAYERPlatform define for web player content (this includes Windows and Mac Web player executables).
UNITY_WIIPlatform define for compiling/executing code for the Wii console.
UNITY_IPHONEPlatform define for compiling/executing code for the iPhone platform.
UNITY_ANDROIDPlatform define for the Android platform.
UNITY_PS3Platform define for running PlayStation 3 code.
UNITY_XBOX360Platform define for executing Xbox 360 code.
UNITY_NACLPlatform define when compiling code for Google native client (this will be set additionally to UNITY_WEBPLAYER).
UNITY_FLASHPlatform 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_6Platform define for the major version of Unity 2.6.
UNITY_2_6_1Platform define for specific version 1 from the major release 2.6.
UNITY_3_0Platform define for the major version of Unity 3.0.
UNITY_3_0_0Platform define for the specific version 0 of Unity 3.0.
UNITY_3_1Platform define for major version of Unity 3.1.
UNITY_3_2Platform define for major version of Unity 3.2.
UNITY_3_3Platform define for major version of Unity 3.3.
UNITY_3_4Platform define for major version of Unity 3.4.
UNITY_3_5Platform 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. 任博学说:

    大家都说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

  2. ESIANG说:

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

  3. 英璐铮说:

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

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

  5. 胡豪翔说:

    Android 需要设置权限麽?

  6. 田大爷说:

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

  7. yx8728说:

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

  8. 吴捷宏说:

    http://pan.baidu.com/share/link?shareid=381875&uk=1292046891这是android_sqlite_last_insert_rowid.unitypackage的下载地址。求帮忙解决。

    • 你检查一下你的文件吧。。。

      • 吴捷宏说:

        最后弄好了,少了那几个dll文件……

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

          • wjh说:

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

          • wjh说:

            做了点改动,加载不了主要是因为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–“; } }

          • wjh说:

            做了点改动,加载不了主要是因为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–“; }}

  9. 吴捷宏说:

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

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

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

  12. 火龙出水说:

    好文章

  13. 火龙出水说:

    强烈支持

  14. 海鹏说:

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

  15. 感谢MOMO说:

    学习了, 感谢MOMO的分享!

  16. zoutao_139说:

    好文章我顶

留下一个回复

你的email不会被公开。 必填项已用 * 标注。