如果大家对Unity中如何使用数据库还不是很了解那么请看我之前的这篇文章。Unity3D研究院之使用C#语言建立本地数据库(二十三)本篇文章我们讨论如何在Unity中打开一个第三方数据库配合Android与编辑器进行同步开发。如下图所示,这个是我目前工程的结构,为了方便调试MOMO使用预定义标签将编辑器与Android平台区分开,方便编辑器与Android平台同时调试。
下图如果看的不清楚,点击图片可查看大图。 不仅在Unity编辑器中可以显示数据库读取的内容,直接编译在真机中也可以显示数据库读取的内容。
按照上图所示我们把第三方数据库放在Plugins->Android->assets中,切记必须放在这里,否无无效,然后是代码。这个第三方数据库是MOMO以前做测试一个号码归属地的时候制作的。所以数据库的内容还是比较大的,蛤蛤。
DbAccess.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
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直接把它挂在摄像机对象身上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
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祝大家学习愉快,哇咔咔,晚安啦啦啦~~
- 本文固定链接: https://www.xuanyusong.com/archives/1454
- 转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
一直说没有libsqlite.so,可实际上是有的啊
是不是还要什么权限啊,我已经走到Open了,报错dbConnection.Open ();啊
搞了一天一夜,原来就是这问题,感谢!
手机上已经不行了,移过来的数据库没有内容,而且还不能创建表格,加入数据,不知道要怎么搞啊
在安卓上数据库读取成功了但是写入信息失败了,求解
你好,请问你使用的是什么方法读取到的,能分享下吗?我能在Application.persistentDataPath文件夹下找到该文件,但是不能使用协程加载也不能读取数据
数据库文件 一旦连接 导致文件被占用 无法被删除 求解
对的 只要u3d运行了就不能删除了
博主,请问下libsqlite3.so文件是怎么生成的?我试了下如果没有这个文件,安卓上是无法正常运行的。
这是库文件吧。。libsqlite
解决了吗。求帮忙
UNITY_STANDALONE_WIN 和 UNITY_STANDALONE_OSX 没说呀,该怎么处理
UNITY_IPHONE是怎么用啊
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 ” “); GUILayout.Box(“qq=” qq ” “); GUILayout.Box(“email=” email ); }显示也改为数组可是。。 name = reader.GetString(reader.GetOrdinal(“name”));这个报错 不知道怎么改 求指导我是新手大神
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 +” “); GUILayout.Box(“qq=” + qq +” “); GUILayout.Box(“email=” + email ); }显示也改为数组可是。。 name = reader.GetString(reader.GetOrdinal(“name”));这个报错 不知道怎么改 求指导我是新手大神
你好,能留下联系方式吗
搞了一天一夜,原来就是这问题,感谢!
松哥,我也遇到了同样的问题,在编辑器里可以但是在真机中不行,求解决啊
不好意思 文章太早了。 我也好久没做过这快了。。
谢谢您,松哥
遇到了同样的问题,请问解决了吗
你们现在解决了吗?我这里也出这个问题了
大神,我的也倒不出来.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_’怎么处理一下呢?谢谢松哥~
磁盘空间不足了吧
我是直接下的MOMO提供的原文做实验的,在PC没问题, ,真机读不出数据。怎么回事能呢,MOMO能给些提示吗
遇到了同样的问题,请问找到解决方案没?
我也是在PC没问题,直接编辑android ,真机读不出数据。怎么回事能呢,MOMO能给些提示吗