godot+c#使用godot-sqlite连接数据库

发布于:2025-09-15 ⋅ 阅读:(21) ⋅ 点赞:(0)

前言

查阅了很多资料都没有关于godot使用c#连接godot-sqlite的,因此研究出了方法,注意该方法可适用4.5及以上,其他版本未验证

采用如下方法,你可以使用c#操作sqlite实现存档和读档功能

步骤

导入和联通

首先需要下载导入

  • 创建一个游戏项目

在这里插入图片描述

  • 点击[AssetLib]搜索sqlite,等待出现【Godot-SQlite】,并且点击下载

在这里插入图片描述

在这里插入图片描述

  • 然后直接导入到项目,这个时候可以在文件夹看到【addons】文件夹

在这里插入图片描述

  • 点击【项目】-【项目设置】-【插件】,进行勾选启用,注意这里需要addons文件夹在res的根目录下,否则识别不到

在这里插入图片描述

  • 接下来尝试联通数据库,在查阅了很多资料,都说需要通过这个路径加载sqlite插件联通数据库
res://addons/godot-sqlite/bin/gdsqlite.gdns
  • 不知道是不是版本原因实际是没有这个文件的,经过测试最终使用如下实现联通了sqlite数据库
  1. 新建一个node2d节点,然后挂载gd脚本,因为它是适配gd语言的,所以对gd语言的适配性是最好的
  2. gd脚本代码看如下
  3. 编写完毕之后,编译并启动游戏
  4. 观察控制台
  • 建立的脚本名称是SqliteBridge.gd,内容如下
extends Node

func _ready():
	if ClassDB.class_exists("SQLite"):
		var db = ClassDB.instantiate("SQLite")
		db.path = "user://test.db"
		if db.open_db():
			print("数据库打开成功!")
			db.query("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);")
			print("表已经创建或已存在")
			db.close_db()
		else:
			print("打开sqlite数据库失败")
	else:
		print("SQLite类未找到,请确保插件可用并且存在可执行文件.")

启动游戏之后控制台如下

在这里插入图片描述

控制台提示如下

Opened database successfully (C:/Users/xxx/AppData/Roaming/Godot/app_userdata/sqlTest/test.db)
数据库打开成功!
表已经创建或已存在
Closed database (C:/Users/xxx/AppData/Roaming/Godot/app_userdata/sqlTest/test.db)

  • 并且提示你打开的数据库文件的路径是什么,如果顺着路径打开文件夹会看到如下

在这里插入图片描述

  • 通过如上的脚本代码,我们设置访问的数据库路径是user://test.db,设置user://的目的是因为这个路径是可读写的

使用c#操作godot-sqlite

  • 正如前面所说,godot-sqlite是适配gd语言的,如果要通过c#操作这个,必须使用一个桥接代码,中转访问

  • 为了演示方便我这里计划操作一个学生信息表

CREATE TABLE IF NOT EXISTS students (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER NOT NULL,
    grade TEXT
)
  • 那么如上只是一个示例,到正式的开发游戏,你可以把表替换为玩家信息表,物品表,怪物信息表等
  • 同时,为了方便操作,我这里采用了和JAVA的JDBC的模式来操作表,以及进行增删改查
  • 为了可以实现这个,首先我们需要打开游戏项目路径,找到有csproj命名的那层文件夹

在这里插入图片描述

  • 在该文件夹的地址栏输入cmd打开命令行,输入如下
dotnet add package System.Data.SQLite.Core

注意:该操作必须你已经配置好了DOTNET

  • 该操作的目的是为了可以引入System.Data.SQLite,否则项目是否无法引用数据库连接,会报错

那么执行修改之后,以我的项目为例,会从

<Project Sdk="Godot.NET.Sdk/4.4.1">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <EnableDynamicLoading>true</EnableDynamicLoading>
  </PropertyGroup>
</Project>

变成

<Project Sdk="Godot.NET.Sdk/4.4.1">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <EnableDynamicLoading>true</EnableDynamicLoading>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="System.Data.SQLite.Core" Version="1.0.119" />
  </ItemGroup>
</Project>
  • 首先创建一个数据库连接代码

DBConnection.cs

using System;
using System.Data.SQLite;
using Godot;
using System.IO;

public static class DBConnection
{
    private static SQLiteConnection _connection;
    private static string _dbPath = "user://test.db";

    // 获取数据库连接:cite[7]
    public static SQLiteConnection GetConnection()
    {
        if (_connection == null)
        {
            // 确保用户数据目录存在
            string userDir = OS.GetUserDataDir();
            string fullPath = Path.Combine(userDir, "test.db");

            // 如果数据库文件不存在,则创建它
            if (!File.Exists(fullPath))
            {
                SQLiteConnection.CreateFile(fullPath);
            }

            string connectionString = $"Data Source={fullPath};Version=3;";
            _connection = new SQLiteConnection(connectionString);
            _connection.Open();

            // 初始化数据库表
            InitializeTables();
        }

        return _connection;
    }

    // 初始化数据库表:cite[1]
    private static void InitializeTables()
    {
        string createTableSQL = @"
            CREATE TABLE IF NOT EXISTS students (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                age INTEGER NOT NULL,
                grade TEXT
            )";

        using (var command = new SQLiteCommand(createTableSQL, _connection))
        {
            command.ExecuteNonQuery();
        }

        GD.Print("数据库表初始化成功");
    }

    // 关闭数据库连接
    public static void CloseConnection()
    {
        if (_connection != null)
        {
            _connection.Close();
            _connection = null;
            GD.Print("数据库连接已经关闭");
        }
    }
}
  • 创建对应的学生信息类实体

Student.cs

using Godot;
using System;

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Grade { get; set; }

    public Student() { }

    public Student(string name, int age, string grade)
    {
        Name = name;
        Age = age;
        Grade = grade;
    }

    // 重写ToString方法便于输出
    public override string ToString()
    {
        return $"Student [ID: {Id}, Name: {Name}, Age: {Age}, Grade: {Grade}]";
    }
}
  • 创建学生信息表的操作DAO层

StudentDAO.cs

using System;
using System.Data.SQLite;
using System.Collections.Generic;
using Godot;
using System.IO;

public class StudentDAO
{

    private static string GetDbPath()
    {
        string userDir = OS.GetUserDataDir();
        return Path.Combine(userDir, "test.db");
    }
    // 添加学生:cite[1]
    public static bool AddStudent(Student student)
    {
        string dbPath = GetDbPath();
        string connectionString = $"Data Source={dbPath};Version=3;";

        // 使用 using 语句确保连接在使用后会被正确关闭和释放:cite[10]
        using (var connection = new SQLiteConnection(connectionString))
        {
            try
            {
                connection.Open();
                string sql = @"INSERT INTO students (name, age, grade) 
                              VALUES (@name, @age, @grade)";

                using (var command = new SQLiteCommand(sql, connection))
                {
                    command.Parameters.AddWithValue("@name", student.Name);
                    command.Parameters.AddWithValue("@age", student.Age);
                    command.Parameters.AddWithValue("@grade", student.Grade);

                    int rowsAffected = command.ExecuteNonQuery();
                    GD.Print($"新增学生: {student.Name}, 操作结果: {rowsAffected}");
                    return rowsAffected > 0;
                }
            }
            catch (Exception e)
            {
                GD.PrintErr($"添加学生失败: {e.Message}");
                return false;
            }
        } // using 结束处,connection 会被自动 Dispose
    }

    // 根据ID删除学生:cite[5]
    public static bool DeleteStudent(int id)
    {
        string dbPath = GetDbPath();
        string connectionString = $"Data Source={dbPath};Version=3;";

        try
        {
            using (var connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                string sql = "DELETE FROM students WHERE id = @id";

                using (var command = new SQLiteCommand(sql, connection))
                {
                    command.Parameters.AddWithValue("@id", id);

                    int rowsAffected = command.ExecuteNonQuery();
                    GD.Print($"使用ID删除学生: {id}, 操作结果: {rowsAffected}");
                    return rowsAffected > 0;
                }
            }
        }
        catch (Exception e)
        {
            GD.PrintErr($"删除学生失败: {e.Message}");
            return false;
        }
    }

    // 更新学生信息:cite[5]
    public static bool UpdateStudent(Student student)
    {
        string dbPath = GetDbPath();
        string connectionString = $"Data Source={dbPath};Version=3;";
        try
        {
            using (var connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                string sql = @"UPDATE students 
                              SET name = @name, age = @age, grade = @grade 
                              WHERE id = @id";

                using (var command = new SQLiteCommand(sql, connection))
                {
                    command.Parameters.AddWithValue("@name", student.Name);
                    command.Parameters.AddWithValue("@age", student.Age);
                    command.Parameters.AddWithValue("@grade", student.Grade);
                    command.Parameters.AddWithValue("@id", student.Id);

                    int rowsAffected = command.ExecuteNonQuery();
                    GD.Print($"更新学生信息: {student.Name}, 操作结果: {rowsAffected}");
                    return rowsAffected > 0;
                }
            }
        }
        catch (Exception e)
        {
            GD.PrintErr($"更新学生信息失败: {e.Message}");
            return false;
        }
    }

    // 获取所有学生:cite[1]
    public static List<Student> GetAllStudents()
    {
        string dbPath = GetDbPath();
        string connectionString = $"Data Source={dbPath};Version=3;";
        var students = new List<Student>();

        try
        {
            using (var connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                string sql = "SELECT * FROM students";

                using (var command = new SQLiteCommand(sql, connection))
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        students.Add(new Student
                        {
                            Id = Convert.ToInt32(reader["id"]),
                            Name = reader["name"].ToString(),
                            Age = Convert.ToInt32(reader["age"]),
                            Grade = reader["grade"].ToString()
                        });
                    }
                }
            }

            GD.Print($"已获取 {students.Count} 数量学生信息");
        }
        catch (Exception e)
        {
            GD.PrintErr($"获取学生信息失败: {e.Message}");
        }

        return students;
    }

    // 根据ID查询学生:cite[7]
    public static Student GetStudentById(int id)
    {
        string dbPath = GetDbPath();
        string connectionString = $"Data Source={dbPath};Version=3;";
        try
        {
            using (var connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                string sql = "SELECT * FROM students WHERE id = @id";

                using (var command = new SQLiteCommand(sql, connection))
                {
                    command.Parameters.AddWithValue("@id", id);

                    using (var reader = command.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            GD.Print($"使用ID获取学生信息: {id}");
                            return new Student
                            {
                                Id = Convert.ToInt32(reader["id"]),
                                Name = reader["name"].ToString(),
                                Age = Convert.ToInt32(reader["age"]),
                                Grade = reader["grade"].ToString()
                            };
                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            GD.PrintErr($"获取学生信息失败: {e.Message}");
        }

        GD.Print($"未找到学生信息: {id}");
        return null;
    }

    // 根据姓名查询学生(模糊查询):cite[7]
    public static List<Student> GetStudentsByName(string name)
    {
        string dbPath = GetDbPath();
        string connectionString = $"Data Source={dbPath};Version=3;";
        var students = new List<Student>();

        try
        {
            using (var connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                string sql = "SELECT * FROM students WHERE name LIKE @name";

                using (var command = new SQLiteCommand(sql, connection))
                {
                    command.Parameters.AddWithValue("@name", $"%{name}%");

                    using (var reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            students.Add(new Student
                            {
                                Id = Convert.ToInt32(reader["id"]),
                                Name = reader["name"].ToString(),
                                Age = Convert.ToInt32(reader["age"]),
                                Grade = reader["grade"].ToString()
                            });
                        }
                    }
                }
            }

            GD.Print($"已获取 {students.Count} 行数据包含该名称的学生: {name}");
        }
        catch (Exception e)
        {
            GD.PrintErr($"根据名称获取学生失败: {e.Message}");
        }

        return students;
    }
}
  • 新建桥接代码,并且将该脚本绑定到node2d节点上

SQLiteBridge.cs

using Godot;
using System;
using System.Collections.Generic;

public partial class SQLiteBridge : Node2D
{
    public override void _Ready()
    {
        GD.Print("Starting SQLite database operations...");

        // 测试数据库操作
        TestDatabaseOperations();

        GD.Print("All database operations completed");
    }

    private void TestDatabaseOperations()
    {
        // 1. 添加学生
        GD.Print("\n=== 添加学生 ===");
        var student1 = new Student("张三", 20, "大三");
        var student2 = new Student("李四", 19, "大二");
        var student3 = new Student("王五", 21, "大三");

        StudentDAO.AddStudent(student1);
        StudentDAO.AddStudent(student2);
        StudentDAO.AddStudent(student3);

        // 2. 查询所有学生
        GD.Print("\n=== 查询所有学生 ===");
        List<Student> allStudents = StudentDAO.GetAllStudents();
        foreach (var student in allStudents)
        {
            GD.Print(student.ToString());
        }

        // 3. 根据ID查询学生
        GD.Print("\n=== 根据ID查询学生 ===");
        Student retrievedStudent = StudentDAO.GetStudentById(1);
        if (retrievedStudent != null)
        {
            GD.Print($"找到学生: {retrievedStudent}");
        }

        // 4. 根据姓名查询学生
        GD.Print("\n=== 根据姓名查找学生 ===");
        List<Student> studentsByName = StudentDAO.GetStudentsByName("张");
        foreach (var student in studentsByName)
        {
            GD.Print($"找到学生: {student}");
        }

        // 5. 更新学生信息
        GD.Print("\n=== 更新学生信息 ===");
        if (retrievedStudent != null)
        {
            retrievedStudent.Age = 22;
            retrievedStudent.Grade = "大四";
            StudentDAO.UpdateStudent(retrievedStudent);
        }

        // 6. 删除学生
        GD.Print("\n=== 删除学生 ===");
        StudentDAO.DeleteStudent(2);

        // 7. 验证删除结果
        GD.Print("\n=== 验证删除结果 ===");
        List<Student> remainingStudents = StudentDAO.GetAllStudents();
        foreach (var student in remainingStudents)
        {
            GD.Print($"学生: {student}");
        }
    }

    public override void _ExitTree()
    {
    }
}
  • 然后进行编译并且启动游戏

这个时候控制台提示信息如下

在这里插入图片描述

Starting SQLite database operations...

=== 添加学生 ===
[2025-09-14 15:10:49.0435337] System.Data.SQLite (Preload): Native library pre-loader is trying to load native SQLite library "F:\godot_workSpace\SqlTest\.godot\mono\temp\bin\Debug\runtimes\win-x64\native\SQLite.Interop.dll"...
新增学生: 张三, 操作结果: 1
新增学生: 李四, 操作结果: 1
新增学生: 王五, 操作结果: 1

=== 查询所有学生 ===
已获取 3 数量学生信息
Student [ID: 8, Name: 张三, Age: 20, Grade: 大三]
Student [ID: 9, Name: 李四, Age: 19, Grade: 大二]
Student [ID: 10, Name: 王五, Age: 21, Grade: 大三]

=== 根据ID查询学生 ===
未找到学生信息: 1

=== 根据姓名查找学生 ===
已获取 1 行数据包含该名称的学生: 张
找到学生: Student [ID: 8, Name: 张三, Age: 20, Grade: 大三]

=== 更新学生信息 ===

=== 删除学生 ===
使用ID删除学生: 2, 操作结果: 0

=== 验证删除结果 ===
已获取 3 数量学生信息
学生: Student [ID: 8, Name: 张三, Age: 20, Grade: 大三]
学生: Student [ID: 9, Name: 李四, Age: 19, Grade: 大二]
学生: Student [ID: 10, Name: 王五, Age: 21, Grade: 大三]
All database operations completed

  • 然后我们使用工具类,找到本地的test.db打开该数据库,我们就可以看到如下数据

  • 这里我使用dbeaver软件,然后选择SQlite
    在这里插入图片描述
    在这里插入图片描述

  • 然后找到表students,我们就可以看到我们操作的表数据了

在这里插入图片描述

结语

  • 如上我们就实现了通过c#操作godot-sqlite,然后可以用于在游戏的存档和读档