亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Unity3d開發——Sqlite數據庫

2019-11-09 15:18:09
字體:
來源:轉載
供稿:網友

前言

Sqlite是一個輕量級數據庫,在Unity中可以很方便的使用它。比如做AssetBundle資源更新時,可以把AssetBundle的描述信息存放在數據庫中;或者將一些數值表生成數據庫文件,作為游戲的功能配置文件等等。。。

正文

導入步驟

先到Sqlite官網下載對應你系統的Sqlite庫(比如windows64系統,對應 PRecompiled Binaries for Windows sqlite-dll-win64-x64)。

在Unity中Assets目錄下新建Plugins/x86_64目錄,解壓將sqlite3.def和sqlite3.dll放到該目錄下。

由于在代碼中需要使用System.Data和Mono.Data.Sqlite庫,這兩個庫在Unity3d的安裝目錄中有。 在unity安裝目錄/Editor/Data/Mono/lib/mono/2.0下,拷貝System.Data.dll 和 Mono.Data.Sqlite.dll放到Plugins下。

在Player Setting里的 OtherSettings里有個Optimization,下邊的API Compatbility Level 選擇.NET 2.0。

注意,這里我們只下載了windows上的sqltie庫,如果需要在移動端使用則應該去下載對應平臺的sqltie庫。

此時,工程的目錄結構應該是這樣的 工程的目錄結構

接下來,封裝一個Sqlite類,用于對數據庫的一些基本操作,增、刪、改、查等。

Sqlite.cs

using UnityEngine;using System.Collections;using System.Collections.Generic;using Mono.Data.Sqlite;using System.Data;using System;using System.Reflection;using Object = UnityEngine.Object;namespace Hi{ public class Sqlite { //Sqlite連接前綴 private const string DB_CONNECTION_PREFIX = "URI=file:"; //連接器 private IDbConnection m_dbConn; //查詢命令 private IDbCommand m_command; //事物 private IDbTransaction m_dbTrans; public Sqlite(string path) { OpenDataBase(path); } private void OpenDataBase(string path) { m_dbConn = new SqliteConnection(DB_CONNECTION_PREFIX + path); m_dbConn.Open(); m_command = m_dbConn.CreateCommand(); } //查詢函數 //IConfig是自定義的配置類接口,最好使數據庫中的配置類都繼承同一個接口,方便以后擴展 public IEnumerable ExcuteSelectQuery<T>(string sqlQuery) where T : IConfig { return ExcuteSelectQuery(sqlQuery, typeof(T)); } //查詢函數,這里使用反射 反序列數據,簡化對對象的賦值操作 public IEnumerable ExcuteSelectQuery(string sqlQuery, Type type) { //使用事物 BeginTrans(); //查詢語句 m_command.CommandText = sqlQuery; //查詢結果 IDataReader reader = m_command.ExecuteReader(); //反序列化操作 所定義的變量 PropertyInfo[] newpropertys = null; PropertyInfo[] oldpropertys = null; bool init = false; while (reader.Read()) { //創建類對象 IConfig config = Activator.CreateInstance(type) as IConfig; for (int i = 0; i < reader.FieldCount; i++) { if (!init) { //newpropertys將類的屬性 順序的對應到數據庫中的列名,方便后續的賦值操作 if (newpropertys == null) { newpropertys = new PropertyInfo[reader.FieldCount]; } //獲取類的所有屬性 if (oldpropertys == null) { oldpropertys = type.GetProperties(BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.Instance); } //當前數據的列名 string filedName = reader.GetName(i); bool find = false; PropertyInfo pro = null; //查找與列名相同的自定義特性名稱,相同則把查詢到的數據值賦值到對象中 for (int j = 0; j < oldpropertys.Length; j++) { pro = oldpropertys[j]; //獲取自定義特性 object[] objs = pro.GetCustomAttributes(typeof(ConfigFieldAttribute), false); if (objs.Length == 0) { continue; } //特性的列名是否與數據庫中列名相同 ConfigFieldAttribute cfgfield = objs[0] as ConfigFieldAttribute; if (cfgfield.filedName == filedName) { find = true; break; } } newpropertys[i] = find ? pro : null; } //已經排好序的類屬性數組 PropertyInfo info = newpropertys[i]; if (info == null) { continue; } //對象的屬性賦值 info.SetValue(config, reader.GetValue(i), null); } if (!init) { init = true; } yield return config; } Commit(); reader.Close(); } //使用事物 public void BeginTrans() { m_dbTrans = m_dbConn.BeginTransaction(); m_command.Transaction = m_dbTrans; } //事物回滾 public void Rollback() { m_dbTrans.Rollback(); } //事物生效 public void Commit() { m_dbTrans.Commit(); } //執行其他sql語句 public void ExcuteQuery(string sqlQuery) { m_command.CommandText = sqlQuery; m_command.ExecuteNonQuery(); } //關閉連接 public void Close() { if (m_dbTrans != null) { m_dbTrans.Dispose(); m_dbTrans = null; } if (m_command != null) { m_command.Dispose(); m_command = null; } m_dbConn.Close(); m_dbConn = null; } }}

中間那段查詢函數寫得有點麻煩,它的功能是把查詢到的一行數據賦值給一個新對象,后面會詳細說明

IConfig.cs

namespace Hi{ //這里只是想把所有的數據庫配置類抽出一個接口,方便以后擴展 public interface IConfig { }}

ConfigFieldAttribute.cs

using UnityEngine;using System.Collections;using System;namespace Hi{ //自定義配置類特性,用于跟數據庫中單條數據匹配 [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] public class ConfigFieldAttribute : Attribute { public string filedName { get; private set; } public ConfigFieldAttribute(string name) { filedName = name; } }}

TestConfig.cs

using UnityEngine;using System.Collections;using Hi;public class TestConfig : IConfig{ //對應數據庫中列名為ID的數據 [ConfigField("ID")] public string m_id { get; set; } [ConfigField("Name")] public string m_name { get; set; } [ConfigField("Len")] public int m_len { get; set; } public override string ToString() { return string.Format("Id : {0}, Name : {1}, Len : {2}", m_id, m_name, m_len); }}

Test.cs

using UnityEngine;using System.Collections;using Hi;using System.Text;public class Test : MonoBehaviour{ private Sqlite m_sqlite; private const string TABLE_NAME = "UnityTest"; // Use this for initialization void Start() { //數據庫地址 string dbPath = application.dataPath + "/test.db"; m_sqlite = new Sqlite(dbPath); //創建新表 CreateTable(); //插入數據 TestConfig tc1 = new TestConfig { m_id = "001", m_name = "test1", m_len = 10 }; InsertTable(tc1); //在插入一條 TestConfig tc2 = new TestConfig { m_id = "002", m_name = "test2", m_len = 20 }; InsertTable(tc2); //查詢數據 SelectTable(); //更新數據 tc2.m_name = "johnny"; tc2.m_len = 5; UpdateTable(tc2); SelectTable(); } void OnDestroy() { m_sqlite.Close(); } private void CreateTable() { StringBuilder sql = new StringBuilder(); sql.Append("create table "); sql.Append(TABLE_NAME); sql.Append("(ID VARCHAR(255) PRIMARY KEY,"); sql.Append("Name VARCHAR(255),"); sql.Append("Len INT);"); Excute(sql.ToString()); } private void InsertTable(TestConfig tc) { StringBuilder sql = new StringBuilder(); sql.Append("insert into "); sql.Append(TABLE_NAME); sql.Append(" values ('"); sql.Append(tc.m_id); sql.Append("','"); sql.Append(tc.m_name); sql.Append("',"); sql.Append(tc.m_len); sql.Append(");"); Excute(sql.ToString()); } private void SelectTable() { string sql = "select * from " + TABLE_NAME; foreach (var tc in m_sqlite.ExcuteSelectQuery<TestConfig>(sql)) { Debug.Log(tc); } } private void UpdateTable(TestConfig tc) { StringBuilder sql = new StringBuilder(); sql.Append("update "); sql.Append(TABLE_NAME); sql.Append(" set Name = '"); sql.Append(tc.m_name); sql.Append("', Len = "); sql.Append(tc.m_len); sql.Append(" where ID = '"); sql.Append(tc.m_id); sql.Append("';"); Excute(sql.ToString()); } private void Excute(string sql) { Debug.Log(sql.ToString()); m_sqlite.ExcuteQuery(sql); }}

創建表、插入數據、更新數據這些都是直接執行sql語句沒什么可說的,但要注意的是在插入和更新多條數據時,使用事物會使效率提高很多。具體的方法就是在執行語句前調用BeginTrans()函數,執行后調用Commit()函數,如果有異常就回滾,參考ExcuteSelectQuery函數。

重點說一下查詢操作,也就是ExcuteSelectQuery這個函數。 一般情況下,在數據庫中獲得一行數據時,這一行數據應該是能跟某個類對象的屬性或字段一一對應的,也就是反序列化。但是反序列化的過程是繁瑣、重復的,如果數據庫中的每一個表都要去寫對應的反序列化函數真是太麻煩了(誰讓我們很懶呢╮(╯▽╰)╭)。為了簡化這個過程,定義一個特性ConfigFieldAttribute,其filedName 屬性就對應數據庫中的列名(當然也可以方便的將屬性名稱直接對應為數據庫中的列名),這樣一來,只需給對應屬性加上特性,即可完成反序列化,這里通過反射完成這一過程。

最后,Unity中運行結果: 這里寫圖片描述

此時,項目中會生成一個test.db文件,用數據庫可視化工具打開 這里寫圖片描述

大功告成?。。?/strong>最后放上自己的Unity工程。

第一篇文章,可能有些地方描述的不很清楚,如果有什么問題,歡迎大家指出?。。?/p>

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品91视频| 国产精品国产自产拍高清av水多| 欧美一区二区三区艳史| 欧美日韩一区二区免费在线观看| 色偷偷噜噜噜亚洲男人的天堂| 亚洲美女av电影| 欧美另类暴力丝袜| 欧美色欧美亚洲高清在线视频| 国产精品美女主播在线观看纯欲| 欧美成人午夜激情| 98精品国产高清在线xxxx天堂| 亚洲精品一区二区在线| 狠狠色狠狠色综合日日五| 精品激情国产视频| 日韩成人在线电影网| 国产在线观看精品一区二区三区| 超碰精品一区二区三区乱码| 久久久亚洲国产| 久久伊人精品天天| 欧美精品18videosex性欧美| 欧美精品精品精品精品免费| 国产精品欧美一区二区三区奶水| 亚洲欧美日韩国产成人| 国产视频在线一区二区| 国产成人精品日本亚洲| 日韩精品极品在线观看| 久久亚洲精品小早川怜子66| 亚洲无av在线中文字幕| 久久久亚洲国产天美传媒修理工| 2025国产精品视频| 亚洲第一天堂无码专区| 精品亚洲永久免费精品| 国产精品香蕉av| 57pao国产精品一区| 亚洲黄色在线看| 欧美激情亚洲一区| 亚洲视频综合网| 色偷偷偷亚洲综合网另类| 久久精品国产一区| 亚洲欧美日韩中文在线制服| 中文字幕日本精品| 欧美性受xxx| 日韩在线观看高清| 国产精品电影在线观看| 中国china体内裑精亚洲片| 日本精品久久久久久久| 欧美一区二区三区免费视| 最新国产成人av网站网址麻豆| 亚洲午夜精品久久久久久久久久久久| 国产精品视频在线观看| 2019中文在线观看| 热久久99这里有精品| 国产亚洲精品一区二555| 亚洲精品天天看| 久久国产天堂福利天堂| 亚洲第一中文字幕在线观看| 国产91精品久久久久久| 国产精品香蕉av| 性夜试看影院91社区| 亚洲成人黄色在线| 精品国产一区二区三区久久狼黑人| 日韩视频免费在线| 国内精品国产三级国产在线专| 国产成人高潮免费观看精品| 亚洲毛片在线观看.| 亚洲久久久久久久久久久| 伊人青青综合网站| 成人国产精品免费视频| 91精品国产91久久久久久| 欧洲亚洲免费视频| 一色桃子一区二区| 国产91精品久久久久久久| 国产日韩专区在线| 亚洲精品自产拍| 国产91精品久| 国产精品视频地址| 国产精品免费在线免费| 欧美日韩亚洲精品内裤| 欧美xxxx18国产| 亚洲永久免费观看| 亚洲欧美日本伦理| 97av在线视频免费播放| 欧美日韩精品在线播放| 国产精品久久一区| 午夜精品久久久久久久久久久久| 欧美午夜精品久久久久久人妖| 国产精品成久久久久三级| 色婷婷亚洲mv天堂mv在影片| 欧美成人三级视频网站| 欧美激情性做爰免费视频| 少妇高潮久久77777| 久久久精品亚洲| 国产日韩欧美综合| 久久免费精品视频| 日本高清不卡的在线| 久久成人亚洲精品| 精品亚洲国产成av人片传媒| 久久精品影视伊人网| 秋霞成人午夜鲁丝一区二区三区| 在线观看久久久久久| 久久av在线播放| 最近2019中文免费高清视频观看www99| 国产免费一区二区三区在线能观看| 亚洲精品一区二区久| 麻豆乱码国产一区二区三区| 在线视频亚洲欧美| 97超碰蝌蚪网人人做人人爽| 亚洲精品电影在线观看| 色综合久久中文字幕综合网小说| 在线视频国产日韩| 伊人伊成久久人综合网站| 亚洲xxxxx性| 亚洲精品v欧美精品v日韩精品| 欧美日韩亚洲精品内裤| 91a在线视频| 欧美www视频在线观看| 日韩中文字幕久久| 尤物九九久久国产精品的分类| 成人国产精品av| 欧美精品日韩三级| 国产精品高清免费在线观看| 亚洲一区美女视频在线观看免费| 中文字幕久热精品视频在线| 久久在线精品视频| 中文字幕亚洲欧美一区二区三区| 按摩亚洲人久久| 久久天天躁狠狠躁夜夜躁2014| 欧美一级视频在线观看| 国产精品h片在线播放| 中文国产亚洲喷潮| 国产精品第2页| 久久国产一区二区三区| 夜夜躁日日躁狠狠久久88av| 久久久女人电视剧免费播放下载| 91精品国产高清久久久久久91| 丝袜亚洲欧美日韩综合| 亚洲视频网站在线观看| 欧美色道久久88综合亚洲精品| 欧美丰满少妇xxxxx| 亚洲一区亚洲二区| 成人午夜激情免费视频| 91精品视频在线免费观看| 欧美老妇交乱视频| 久久久999精品视频| 久久中文字幕国产| 日韩免费在线播放| 国产欧美va欧美va香蕉在| 日韩免费av在线| 亚洲欧美激情另类校园| 精品亚洲一区二区三区四区五区| 青青草国产精品一区二区| 亚洲国产精品一区二区三区| 欧美丝袜第一区| 国产亚洲人成a一在线v站| 日本一欧美一欧美一亚洲视频| 国产精品入口福利| 日韩精品日韩在线观看| 国产美女91呻吟求| 国产一区二区在线免费视频| 91影院在线免费观看视频| 国产精品第一视频| 亚洲一区二区三区777| 成人福利视频网| 久久精品影视伊人网|