Godot Engine SQLite 完整介绍与实例
引言
在游戏开发中,数据存储是不可或缺的一部分。无论是保存玩家进度、管理物品库存、存储用户设置,还是处理动态任务数据,选择一个高效且易于集成的数据库解决方案都至关重要。对于Godot Engine项目而言,SQLite是一个极佳的选择。它是一个轻量级、无服务器、自包含且基于文件的关系型数据库管理系统,避免了独立数据库服务器的开销,非常适合本地数据存储需求。
本文将详细介绍如何在Godot Engine中集成和使用SQLite,包括插件安装、数据库连接、以及基本的CRUD(创建、读取、更新、删除)操作。
1. Godot-SQLite 插件设置
在Godot 4.x 项目中,推荐使用 godot-sqlite 插件来集成SQLite,该插件可在Godot资源库中找到。
安装步骤:
- 打开 Godot Engine: 启动您的Godot项目。
- 访问 AssetLib: 点击编辑器顶部的 “AssetLib” 标签。
- 搜索 “godot-sqlite”: 在搜索栏中输入 “godot-sqlite” 并从结果中选择该插件。
- 下载并安装: 点击 “Download”,下载完成后点击 “Install”。
- 激活插件: 进入
项目(Project)->项目设置(Project Settings)->插件(Plugins),确保Godot-SQLite插件已启用。
2. 核心概念与使用实例
安装并启用插件后,您可以使用GDScript与SQLite数据库进行交互。
2.1. 初始化和数据库连接
首先,您需要预加载SQLite类并创建一个实例。path 变量指定数据库文件的存储位置。如果数据库文件不存在,它将被创建。您可以将数据库存储在 res://(项目资源,导出后只读)或 user://(用户特定数据,可写入)目录。
“`gdscript
extends Node
const SQLite = preload(“res://addons/godot-sqlite/bin/gdsqlite.gdns”) # 插件 GDNative 脚本路径
var db: SQLite
var db_path: String = “user://game_data.db” # 数据库文件将存储在用户数据目录
func _ready():
db = SQLite.new()
db.path = db_path
if db.open_db() != OK:
print("无法打开数据库: ", db.error_message)
return
print("数据库成功打开。")
# 示例调用 (下文将定义)
create_player_table()
insert_player_data("Alice", 100)
insert_player_data("Bob", 150)
insert_player_data_with_bindings("Charlie", 200)
query_all_players()
update_player_score("Alice", 120)
query_player_by_name("Alice")
delete_player_data("Bob")
query_all_players()
db.close_db()
print("数据库已关闭。")
“`
2.2. 创建表
您可以使用 create_table() 方法或执行原始SQL CREATE TABLE 语句来创建表。create_table() 方法期望一个字典来定义表结构。
“`gdscript
func create_player_table():
var table_schema = {
“table_name”: “players”,
“columns”: [
{“name”: “id”, “type”: “INTEGER”, “primary_key”: true, “autoincrement”: true},
{“name”: “name”, “type”: “TEXT”, “not_null”: true},
{“name”: “score”, “type”: “INTEGER”, “default”: 0}
]
}
var result = db.create_table(table_schema)
if result != OK:
print("无法创建表 'players': ", db.error_message)
else:
print("表 'players' 已创建或已存在。")
# 或者,使用原始 SQL:
# var query = "CREATE TABLE IF NOT EXISTS highscores (id INTEGER PRIMARY KEY AUTOINCREMENT, player_name TEXT NOT NULL, score INTEGER DEFAULT 0);"
# var result_raw = db.query(query)
# if result_raw.size() == 0 and db.error_message != "":
# print("无法使用原始SQL创建表 'highscores': ", db.error_message)
# else:
# print("表 'highscores' 已创建或已存在 (原始SQL)。")
“`
2.3. 插入数据
您可以使用 insert_row() 进行简单的键值插入,或者使用 query_with_bindings() 进行更复杂或参数化的 INSERT 语句。使用绑定对于防止SQL注入至关重要。
“`gdscript
func insert_player_data(name: String, score: int):
var data = {
“name”: name,
“score”: score
}
var result = db.insert_row(“players”, data)
if result != OK:
print(“无法插入玩家数据: “, db.error_message)
else:
print(“已插入玩家: %s 成绩: %d” % [name, score])
func insert_player_data_with_bindings(name: String, score: int):
var query = “INSERT INTO players (name, score) VALUES (?, ?);”
var bindings = [name, score]
var result = db.query_with_bindings(query, bindings)
if result.size() == 0 and db.error_message != “”:
print(“无法通过绑定插入玩家数据: “, db.error_message)
else:
print(“已插入玩家 (通过绑定): %s 成绩: %d” % [name, score])
“`
2.4. 查询数据 (SELECT)
使用 query() 进行原始SQL查询,或使用 query_with_bindings() 进行参数化查询。结果是一个 Array,其中包含 Dictionaries,每个字典代表一行数据。
“`gdscript
func query_all_players():
var query = “SELECT id, name, score FROM players ORDER BY score DESC;”
var result = db.query(query)
if result.size() == 0 and db.error_message != "":
print("无法查询所有玩家: ", db.error_message)
return
print("--- 所有玩家 ---")
for row in result:
print("ID: %d, 姓名: %s, 成绩: %d" % [row["id"], row["name"], row["score"]])
print("-------------------")
func query_player_by_name(name: String):
var query = “SELECT id, name, score FROM players WHERE name = ?;”
var bindings = [name]
var result = db.query_with_bindings(query, bindings)
if result.size() == 0 and db.error_message != "":
print("无法按姓名查询玩家: ", db.error_message)
return
if result.empty():
print("未找到玩家 '%s'。" % name)
else:
var player_data = result[0]
print("找到玩家: ID: %d, 姓名: %s, 成绩: %d" % [player_data["id"], player_data["name"], player_data["score"]])
“`
2.5. 更新数据
使用 update_row() 或 query_with_bindings()(用于 UPDATE 语句)来更新现有记录。
“`gdscript
func update_player_score(name: String, new_score: int):
var data_to_update = {
“score”: new_score
}
var where_clause = {
“name”: name
}
var result = db.update_row(“players”, data_to_update, where_clause)
if result != OK:
print(“无法更新玩家 ‘%s’ 的成绩: ” % name, db.error_message)
else:
print(“已将玩家 ‘%s’ 的成绩更新为 %d。” % [name, new_score])
# 或者,使用带有绑定的原始SQL:
# var query = "UPDATE players SET score = ? WHERE name = ?;"
# var bindings = [new_score, name]
# var result_raw = db.query_with_bindings(query, bindings)
# if result_raw.size() == 0 and db.error_message != "":
# print("无法使用原始SQL更新玩家 '%s' 的成绩: " % name, db.error_message)
# else:
# print("已将玩家 '%s' 的成绩更新为 %d (原始SQL)。" % [name, new_score])
“`
2.6. 删除数据
使用 delete_row() 或 query_with_bindings()(用于 DELETE 语句)来删除记录。
“`gdscript
func delete_player_data(name: String):
var where_clause = {
“name”: name
}
var result = db.delete_row(“players”, where_clause)
if result != OK:
print(“无法删除玩家 ‘%s’: ” % name, db.error_message)
else:
print(“已删除玩家: %s。” % name)
# 或者,使用带有绑定的原始SQL:
# var query = "DELETE FROM players WHERE name = ?;"
# var bindings = [name]
# var result_raw = db.query_with_bindings(query, bindings)
# if result_raw.size() == 0 and db.error_message != "":
# print("无法使用原始SQL删除玩家 '%s': " % name, db.error_message)
# else:
# print("已删除玩家 '%s' (原始SQL)。" % name)
“`
2.7. 错误处理
始终检查数据库操作的返回值和 db.error_message 属性来处理潜在问题。
“`gdscript
错误处理已在上述每个函数中演示。
如果操作失败,db.error_message 属性将包含一个人类可读的错误字符串。
“`
结论
通过 godot-sqlite 插件,Godot Engine 项目可以轻松地集成和利用SQLite数据库进行本地数据存储。本文详细介绍了从插件安装到各种数据库操作的完整流程,并提供了GDScript实例。请记住,在实际开发中,始终使用参数化查询(query_with_bindings)来有效防止SQL注入漏洞,确保游戏数据的安全性和完整性。