GDSCript提供了丰富的功能,在数据存取方面,XML、JSON、CSV、ConfigFile都支持的不错,基础的纯文本、二进制存储乃至加密都有一定的涉及。
但是文件存储数据的方式仍然有很多局限,比如查询和修改操作等。在小数据量的时候可能没有什么问题,但是涉及大量的数据时,文件操作就会显得十分低效。
另一方面,如果你想用Godot开发一些复杂的应用程序,尤其是与结构化存储的数据有关的,基于文件存储数据也是很没有效率的。
数据库作为脱胎于文件系统,专用于数据存储的一种形式,推动了软件和互联网的发展。选择使用数据库和其强大的SQL查询语言,会比自己自定义一个文件格式和造一套函数库来存取要高效和标准的多。
在Godot中,虽然没有原生提供数据库的使用,但是已经存在一些第三方插件可以让你使用数据库。Godot SQLite就是其中之一。
Godot SQlite是一个GDNative插件,可以方便的在Godot中创建和使用SQLite3数据库,其目前支持在Godot 3.2及以上版本中使用。另外,它不需要任何额外的编译或构建脚本。也不需要再单独安装SQLite3。
Godot SQlite提供了一个类,用于在GDScript中创建SQLite3数据库,并且提供了一些列属性和方法,方便管理数据库和对数据表进行增删改查操作。
有两种方法安装Godot SQlite,一种方式是通过Godot的AssetLib安装,另一种是从GitHub的仓库页面手动下载源码压缩包,下载后解压安装。这里我们采用前一种方式。
国内用户Godot的资产库可能有图片显示不全、以及下载缓慢等情况,如果一次下载不成功可以进行重试,如果还不行则可能需要代理。
安装完成后,就可以开始实际的使用了,但首先我们要在Godot编辑器中启用它。
在Godot要使用godot sqlite,首先需要导入和引用它。
var sqllite = preload("res://addons/godot-sqlite/bin/gdsqlite.gdns")
上面的代码中我们申明变量sqllite
,然后用Godot的资源预加载方法preload()
导入res://addons/godot-sqlite/bin/
目录下的gdsqlite.gdns
文件。.gdns
文件是Godot的GDNative编译后的文件。
引入后,sqllite
就是一个类,我们可以用new()
方法创建它的实例。
# 导入和引用
var sqllite = preload("res://addons/godot-sqlite/bin/gdsqlite.gdns")
var db # 数据库对象
func _ready():
db = sqllite.new() # 创建实际的数据库对象
db
是“database”的缩写,它实际是sqllite
的一个实例。因此我们可以通过db
来调用sqllite
提供的一系列属性和方法进行sqllite数据库和表的增删改查。但是用代码来创建数据库和数据库表有些不直观,如果可以采用可视化的程序来完成数据库的和表的初期构建,然后再在程序中实现实际的应用逻辑就好了。
好在是真的存在这样的工具。
“DB Browser for SQlite”是一款非常小巧(.zip压缩包约19M)实用的SQlite数据库可视化管理软件,你可以到官网下载。
官网:http://www.sqlitebrowser.org/
下载后不需要安装,解压缩后,找到同名.exe主程序,双击打开即可使用。
其界面甚至自带完整汉化。
数据库管理软件的理念和操作大同小异,你完全没有必要慌张,分分钟就可以上手。
在当前Godot项目“res://”目录下创建“database”文件夹(名称可以是其他的)。
然后右键点击“在资源管理器中打开”。打开资源管理器后,复制路径。
在“DB Browser for SQlite”中点击顶部工具栏“新建数据库”按钮,在弹出的“保存文件”对话框中将之前拷贝的路径粘贴到文件名处,回车,定位到我们的Godot项目资源文件夹下的“database”文件夹。
然后输入要保存的数据库名称,比如“test1”,点击“保存”。
此时,“database”文件夹下就会创建有“test1.db”文件。说明数据库文件创建成功。
此时,“DB Browser for SQlite”中会自动弹出“编辑表定义”对话框,用于创建数据库中的第一个表。
首先输入表的名称,然后定义表的字段,字段设定完毕后,点击“ok”,第一个表格就建好了。
insert_row()
方法来向表格中新增记录。Control
为根节点的场景。然后为其添加代码如下:extends Control
var sqllite = preload("res://addons/godot-sqlite/bin/gdsqlite.gdns")# 导入和引用
var db # 数据库对象
var db_path = "res://database/test1.db" # 数据库名称和保存路径
var table_name = "godoter" # 表格名称
func _ready():
db = sqllite.new() # 创建实际的数据库对象db
db.path = db_path # 指定数据库文件
db.open_db()
# 向指定数据表追加新的记录
var new_rec = {"name":"张三","sex":"2","age":"25"}
var success = db.insert_row(table_name,new_rec)
if success:
print("数据插入成功")
db.close_db()
在上面的代码中:
db_path
变量存储我们之前用“DB Browser for SQlite”创建的数据库test1.db
的路径table_name
存储数据表的名称"godoter"。在_ready()
中:
sqllite
的实例并存储在全局变量db
中。path
属性值为db_path
,也就是我们的数据库文件的路径。open_db()
方法实际的打开数据库文件;insert_row()
方法向数据表"godoter"中插入了一条记录,并用变量success
接收是否插入成功;close_db()
方法关闭打开的数据库。可以看到,open_db()
和close_db()
很像GDScript中处理文件时的file.open()
和file.close()
。打开 -> 操作 -> 关闭,流程相似,目的也相似,就是为了释放文件的占用。
insert_row()
方法需要传入两个参数:
为了代码的清晰和可以复用,我们可以简单的封装一下,封装出如下的一个函数。
# 向指定数据表追加新的记录
func append_rec(db_path:String,table_name:String,rec:Dictionary):
var db = sqllite.new() # 创建实际的数据库对象db
db.path = db_path # 指定数据库文件
# 实际操作
db.open_db()
var success = db.insert_row(table_name,rec)
if success:
print("数据插入成功")
db.close_db()
代码也就可以改进为:
extends Control
var sqllite = preload("res://addons/godot-sqlite/bin/gdsqlite.gdns")# 导入和引用
var db_path = "res://database/test1.db" # 数据库名称和保存路径
var table_name = "godoter" # 表格名称
func _ready():
var new_rec = {"name":"张三","sex":"2","age":"25"}
append_rec(db_path,table_name,new_rec)
# 向指定数据表追加新的记录
func append_rec(db_path:String,table_name:String,rec:Dictionary):
var db = sqllite.new() # 创建实际的数据库对象db
db.path = db_path # 指定数据库文件
# 实际操作
db.open_db()
var success = db.insert_row(table_name,rec)
if success:
print("数据插入成功")
db.close_db()
进一步,就可以使用LineEdit、TextEdit等等Godot控件设计表单,用于显示和输入数据了。Godot数据库应用的开发也就开启了。
注意
“DB Browser for SQlite”运行的情况下,测试运行上面的场景和代码,将可能因为test1.db
已经被打开和占用,而在Godot报错,无法正常将记录插入到表中。此时就需要先关闭“DB Browser for SQlite”了。
数据库存在的意义就是为了方便管理数据,创建数据只是其中的一步,在海量的数据中查询和检索数据才是其最大的用途。传统的SQL一直都是用经典的select
语句开进行数据查询的,它的形式如下:
select * from <table_name>;
这里,我们可以使用query()
方法传入一个构造好的select
语句来实现数据的查询。
同样我们为了代码的简洁和清晰封装一个函数。
# 返回包含某个数据表的所有数据记录的数组
func load_table_recs(db_path:String,table_name:String) -> Array:
var results = []
var db = sqllite.new() # 创建实际的数据库对象db
db.path = db_path # 指定数据库文件
# 实际操作
db.open_db()
db.query("select * from " + table_name + ";")
results = db.query_result
db.close_db()
return results
上面代码中,我们构造了一个SQL查询语句,作为query()
方法的参数, 执行后将从指定名称的数据表中查找到所有的数据记录,并以数组的形式返回结果,结果保存在query_result
属性中。其中,每条记录是一个单独的字典形式。
提示
上面的封装只是一个基础形式,既没有条件判断也没有分页、排序之类的,实际的数据库应用中是不可能封装成这样的,但是目前为止,我们的数据表中只有几条屈指可数的数据,完全不会有什么问题,也有助于大家理解。
整个测试代码如下:
extends Control
var sqllite = preload("res://addons/godot-sqlite/bin/gdsqlite.gdns")# 导入和引用
var db_path = "res://database/test1.db" # 数据库名称和保存路径
var table_name = "godoter" # 表格名称
func _ready():
var new_rec = {"name":"张三","sex":"2","age":"25"}
print(load_table_recs(db_path,table_name))
# 返回包含某个数据表的所有数据记录的数组
func load_table_recs(db_path:String,table_name:String) -> Array:
var results = []
var db = sqllite.new() # 创建实际的数据库对象db
db.path = db_path # 指定数据库文件
# 实际操作
db.open_db()
db.query("select * from " + table_name + ";")
results = db.query_result
db.close_db()
return results
上面代码执行之后输出结果:
[{age:25, name:张三, sex:1}, {age:52, name:李四, sex:1}, {age:35, name:王五, sex:0}, {age:25, name:张三, sex:2}]
到这一步基础的查询和获取数据库中的数据已经实现了,通过简单的遍历,你就可以将它们运用到你的项目中。
好了,这里只做抛砖引玉,具体的数据库使用还要有赖于对数据库管理及SQL语句等相关知识的了解和对“DB Browser for SQlite”这样的可视化数据库管理软件的学习,以及对Godot SQlite自身所提供的属性和方法的学习。
下文就是对Godot SQlite自身所提供的属性和方法文档的翻译。应该能对您深入学习有所帮助。
补充
数据库设计中有一种图形工具叫E-R图,有兴趣可以自行了解,对数据库的提前设计和规划将有所帮助。