首页 > Unity, 游戏开发 > Unity数据持久化和SQlite

Unity数据持久化和SQlite

2020年2月12日
目录
[隐藏]

1. 比较PlayerPrefs和SQlite

一般来说数据持久化[1]用Unity提供的PlayerPrefs就可以了(实际是不应该的,后面会讲),但PlayerPrefs只支持int、string、float三种数据类型,只能保存一些简单的键值对(即哈希表),如果要保存复杂数据类型,则需要自己组织存储格式,比如用逗号将数据分隔开用来表示一个list,非常容易出错。这种键值对的表示方式是非关系型数据库,优点是速度快,缺点是数据之间缺乏联系,数据无结构化。比如有一些物品叫BlueGem、GreenGem、RedGem,他们都是item,为了保存这些道具的数量和时效,需要用

item_BlueGem_Count       12

item_BlueGem_Time         1

或者

item_BlueGem                 12,1

的形式表示一个叫BlueGem的item有12个且1天后会过期,item前缀表示这个key的类型是item,BlueGem表示具体的物品,Count和Time表示物品不同的属性。如果按第一种做法,为了保存物品的两个属性就需要新加两个记录,如果物品属性有10个甚至更多,那保存的数据量将会非常庞大,而且非常不好维护。如果按第二种做法,用逗号分隔不同数据,这样做的问题在于整个值都是字符串,需要对这个字符串进行解析,而且由于它本身没有含义,就需要在文档里定义不同位置的值代表什么,这样很容易由于文档更新不及时,导致数据错乱。

将PlayerPrefs用来存储游戏存档的用法实际上偏离了Unity设计PlayerPrefs的初衷[2]。PlayerPrefs全称Player Preference,这里的player指的是游戏运行时,PlayerPrefs用来存储一些简单的游戏配置,比如是否全屏、分辨率、帧率、画面品质等,而不应该存储游戏存档。在windows平台,PlayerPrefs的数据会保存在注册表里,HKEY_CURRENT_USER\Software\<company_name>\<product_name>,注册表是Windows中的一个重要的数据库,用于存储系统和应用程序的设置信息[3],所以是不适合存储游戏数据的。正确的方法是将游戏存档保存为一个文件放在Application.persistentDataPath目录下。

为了加强数据间的联系,集中管理一类有共性的值(比如都是item),自然而然想到要使用关系型数据库,而且是可以本地读取的数据库,SQlite就是不错的选择。关系型数据库以行和列的形式表示数据,不同的列有不同的预定义含义,不同的行表示单独一条数据。比如针对上面的例子

item table 

item_name item_count item_time
BlueGem 12 1
RedGem 22 4
GreenGem 100 7

比键值对的保存方式要好很多。同时通过使用数据库查看工具比如DB Browsersqlitestudio,能够可视化的管理本地存储的数据库,这点非常方便。

SQlite的使用非常广泛,比如VS2015 Update 2以后 intellisense 使用sqlite代替了原先的*.sdf SQL Server Compact数据库,用来支持智能感知、代码恢复等功能[4]

 

2. 使用SQlite

Unity导入sqlite需要三样东西

  • Mono.Data.Sqlite.dll System.Data.dll 用来提供native dll到C#的绑定以及针对不同平台的处理,在Unity安装目录Editor\Data\Mono\lib\mono\2.0\ 下能找到这两个dll
  • SQlite运行库,从 https://www.sqlite.org/download.html 这里下载,通常需要
    • Precompiled Binaries for Windows (x86和x86_64)
    • Precompiled Binaries for Android

(IOS平台不需要SQlite运行库)

在游戏中,数据库是用来作为本地存储的,在进入游戏的loading阶段对数据库进行解析(读档),将数据全部读出来存在内存里,而不是每次查找\修改\删除都对数据库直接进行操作,因为这些操作是很耗时的,只需要在退出游戏前将内存中的数据写回数据库(存档)即可。

下面是一个处理SQlite数据库的方法类

初始化时调用

dbConnection = new SqliteConnection(path);

时会在对应的path创建连接,如果没有对应的数据库,则会创建一个。在游戏的初始化流程里建立数据库连接,如果不存在数据库的话就新建一个,并创建数据表。存储数据库的路径最好是Application.persistentDataPath,这样能在游戏更新间保证数据持久存在。

需要注意的是数据库路径在不同平台有不同的规定,在windows和IOS需要用

"data source=" + Application.persistentDataPath + "/" + dbFileName;

Android平台需要用

"URI=file:" +  Application.persistentDataPath + "/" + dbFileName;

在这里下载SQlite示例

 

参考资料


[1] 数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称. 数据模型可以是任何数据结构或对象模型,存储模型可以是关系模型、XML、二进制流等。

[2] https://docs.unity3d.com/ScriptReference/PlayerPrefs.html

[3] 在Windows 3.x操作系统中,注册表是一个极小文件,其文件名为Reg.dat,里面只存放了某些文件类型的应用程序关联,大部分的设置是被放在win.ini、system.ini等多个初始化ini文件中。由于这些初始化文件不便于管理和维护,时常出现一些因ini文件遭到破坏而导致系统无法启动的问题。为了使系统运行得更为稳定、健壮,Windows 95/98/me设计师们借用了Windows NT中的注册表的思想,将注册表概念引入到Windows 95/98/me操作系统中,而且将ini文件中的大部分设置也移植到注册表中,因此,注册表在Windows 95/98/me等操作系统的启动、运行过程中起着重要的作用。

[4] https://stackoverflow.com/questions/36407386/what-is-the-vc-db-file-in-visual-studio-projects

分类: Unity, 游戏开发 标签: