Unity连接MySql数据库(基础)
为什么写这篇文章
网上其实已经有了不少unity连接MySql数据库(或其他数据库)的教程视频、文章,但是我找到的都是比较老的,使用较新版本(这里指8.0往后)的MySql connector的教程偏少,于是打算写此文,顺便记录个人学习经历、锻炼相关写作能力。
这是本人第一次写教程,在unity和数据库的方面还处于探索阶段(写此文的前一天晚上才通过ai和其他资料第一次实现了unity和mysql的连接(悲)),如有诸多不严谨之处,还望谅解,并非常欢迎在评论区留下您的建议、指正!
准备工作
我们需要Unity、MySql、MySql Connector三者,且要注意三者版本。
个人使用工具版本:
Unity:2022.3.62f3c1;
MySql:8.0.45;
MySql Connector:8.0.28。
MySql Connector下载链接
注意:MySql Connector 最好同自身MySql版本相近,不然在unity中操作时可能会出现不兼容报错。
在有了上述工具后:
- 我们新建一个Unity工程,名为MySql_TestProject;
- 在项目的project窗口中,新建一个名为 Plugins 的文件夹,以放置我们需要的文件;
- 在Unity安装目录下找到I18N.dll、I18N.West.dll、System.Data.dll、System.Drawing.dll、I18N.CJK.dll、I18N.MidEast.dll文件复制拖入到Plugins文件夹中;
- 在刚刚下载好的MySql Connector安装目录下,选中v4.5.2 或 v4.8文件夹,拖入除MySql.Web.dll外的所有dll文件(老版本只用MySql.Data.dll就行,但是新版本需要其他依赖文件,可能不需要拖入那么多dll,我这里算是偷懒了)
注意:如果添加了MySql.Web.dll,unity中会提示报错(示例):Assembly ‘Assets/Plugins/MySQL/mysql_connector/MySql.Web.dll’ will not be loaded due to errors:
Unable to resolve reference ‘WebMatrix.WebData’. Is the assembly missing or incompatible with the current platform?
Reference validation can be disabled in the Plugin Inspector; - 然后就是开始代码了~
示例项目效果
本教程中,我们希望我们的示例项目可以实现登录、注册功能,界面如下:

示例数据库表
以下是我创建的一个数据库,存储了用户的信息:

简单的MySql连接测试
为了验证我们的unity能正确同MySql数据库进行连接,我们添加以下脚本:
using System.Collections.Generic;
using UnityEngine;
using MySql.Data.MySqlClient; // 注意一定要引用此命名空间才可使用mysql的API
public class DatabaseManager : MonoBehaviour
{
[Header("MySql Connection")]
public string server;
public uint port;
public string userID;
public string password;
public string database;
public string database_table;
[Header("MySql 查询示例命令")]
public string MySQL_cmd;
private MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder();
// MySqlConnectionStringBuilder 是 MySQL Connector/NET 提供的一个连接字符串构建器类,用于类型安全地构建数据库连接字符串。(也可以不适用构建器直接连接字符串,但是不推荐)
void Awake()
{
#region 配置连接串
// 使用 MySqlConnectionStringBuilder 构建连接串
builder.Server = server; // 指定 MySQL 服务器的 IP 地址或主机名
builder.Port = port; // 指定 MySQL 服务器监听的端口号
builder.UserID = userID; // 指定连接 MySQL 的用户名
builder.Password = password; // 指定连接 MySQL 的密码
builder.Database = database; // 指定连接后默认使用的数据库名称
builder.CharacterSet = "utf8"; // 指定客户端与服务器通信时使用的字符集
sqlConnection = new MySqlConnection(builder.ToString()); // 创建 MySQL 连接对象
#endregion
#region 简单的mysql连接及查询示例
using (MySqlConnection connection = new MySqlConnection(builder.ToString()))
{
try
{
connection.Open(); // 建立与MySQL服务器的实际网络连接,首次打开可能较慢(握手、认证、加密协商)
Debug.Log("连接 MySQL 成功!");
// 简单查询示例
MySqlCommand command = new MySqlCommand(MySql_cmd + " " + database_table + ";" , connection); // 在给定连接上执行SQL命令
MySqlDataReader dataReader = command.ExecuteReader(); // 执行查询并返回结果,返回一个只读、只进的数据读取器
while (dataReader.Read()) // 逐行读取数据
{
Debug.Log(dataReader.GetString(0)); // 输出第一列数据信息
}
dataReader.Close(); // 关闭读取器
}
catch(MySqlException ex) // 如果连接失败,会抛出MySqlException
{
Debug.LogError("连接失败" + ex.Message);
}
finally
{
if (connection.State == System.Data.ConnectionState.Open)
{
connection.Close();
}
}
}
#endregion
}
}
将此脚本挂载到我们场景上新建的一个空物体(这里我命名为DatabaseManager)上,将各项参数输入后运行程序,就可以看到Unity控制台上打印出数据表第一列的信息。
注:请确保已经创建数据库并添加了表
输入各项参数:

如果连接成功,可以看到输出了数据库我们要查询的表的第一列信息:

到这里,恭喜你已经成功让unity和mysql数据库进行连接了!
注:UI界面的搭建这里不是要讲的重点,先跳过了~
实现登录和注册功能
这里我们要实现的登录功能的核心是实现对mysql数据库中的数据进行查询、比对,我们在DatabaseManager的脚本上直接进行修改。
核心是掌握mysql的相关api、数据库连接及读取流程、sql相关语法及数据库基础操作等,建议看示例代码中的相关注释哦!
直接看代码:
注册 & 从数据库读取用户信息:
using System.Collections.Generic;
using UnityEngine;
using MySql.Data.MySqlClient;
public class DatabaseManager : MonoBehaviour
{
#region 单例实现
private static DatabaseManager _instance;
public static DatabaseManager Instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType<DatabaseManager>();
if (_instance == null)
{
GameObject go = new GameObject("DatabaseManager");
_instance = go.AddComponent<DatabaseManager>();
DontDestroyOnLoad(go);
}
}
return _instance;
}
}
#endregion
[Header("MySql Connection")]
public string server;
public uint port;
public string userID;
public string password;
public string database;
public string database_table;
[Header("MySql 查询示例命令")]
public string MySql_cmd;
[System.Serializable]
public class User // 创建User类便于存储用户信息
{
public string Username;
public string Useraccount;
public string Userpassword;
public User(string new_UserName = " ", string new_UserAccount = " " , string new_UserPassword = " ")
{
Username = new_UserName;
Useraccount = new_UserAccount;
Userpassword = new_UserPassword;
}
}
public List<User> UserInfos = new List<User>(); // 创建用户信息列表
#region sql类
private MySqlConnection sqlConnection;
private MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder();
#endregion
void Awake()
{
#region 配置连接串
// 使用 MySqlConnectionStringBuilder 构建连接串
builder.Server = server;
builder.Port = port;
builder.UserID = userID;
builder.Password = password;
builder.Database = database;
builder.CharacterSet = "utf8";
#endregion
sqlConnection = new MySqlConnection(builder.ToString());
#region 简单的mysql连接及查询示例
using (MySqlConnection connection = new MySqlConnection(builder.ToString()))
{
try
{
connection.Open();
Debug.Log("连接 MySQL 成功!");
// 简单查询示例
MySqlCommand command = new MySqlCommand(MySql_cmd + " " + database_table + ";" , connection);
MySqlDataReader dataReader = command.ExecuteReader();
while (dataReader.Read())
{
Debug.Log(dataReader.GetString(0)); // 输出第一列数据
}
dataReader.Close();
}
catch(MySqlException ex)
{
Debug.LogError("连接失败" + ex.Message);
}
finally
{
if (connection.State == System.Data.ConnectionState.Open)
{
connection.Close();
}
}
}
#endregion
GetUserInfo();
}
#region 将从数据库读取到的信息添加到用户数据列表中
void GetUserInfo()
{
string new_Name , new_Account , new_Password;
sqlConnection.Open();
MySqlCommand mysqlCommand = new MySqlCommand($"select * from {database_table}" , sqlConnection); // 查询命令
MySqlDataReader mySqlDataReader = mysqlCommand.ExecuteReader(); // 执行查询命令并返回一个阅读器
while (mySqlDataReader.Read()) // 逐行读取
{
new_Name = mySqlDataReader.GetString(0);
new_Account = mySqlDataReader.GetString(1);
new_Password = mySqlDataReader.GetString(2);
User newUser = new User(new_Name , new_Account , new_Password);
UserInfos.Add(newUser);
}
sqlConnection.Close();
}
#endregion
#region 增添新的用户数据
public void InsertNewUserInfo(User newUser)
{
sqlConnection.Open();
MySqlCommand check_command = new MySqlCommand("select * from "+database_table , sqlConnection); // 查询表
MySqlDataReader mySqlDataReader = check_command.ExecuteReader(); // 执行查询命令并返回结果集、包装成MySqlDataReader对象
string col0 = mySqlDataReader.GetName(0); // 获取第一个字段名 / 列名
string col1 = mySqlDataReader.GetName(1); // 获取第二个字段名
string col2 = mySqlDataReader.GetName(2); // 获取第三个字段名
mySqlDataReader.Close(); // 关闭阅读器(注意!!!执行下一个命令前要关闭先前打开的阅读器)
MySqlCommand insert_command = new MySqlCommand($"insert into {database_table} ({col0},{col1},{col2}) values ('{newUser.Username}','{newUser.Useraccount}','{newUser.Userpassword}');" , sqlConnection); // 添加新用户信息(注册)
insert_command.ExecuteNonQuery(); // 执行非查询命令
UserInfos.Add(newUser);
sqlConnection.Close(); // 关闭连接
}
#endregion
}
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class RegisterPanel : MonoBehaviour
{
[Header("输入栏控件")]
public TMP_InputField name_InputField;
public TMP_InputField account_InputField;
public TMP_InputField password_InputField;
[Header("提示文本")]
public TMP_Text remind_Text;
#region 注册按钮监听事件
public void onRegisterButtonClick()
{
// 检测用户名是否存在
string input_name = name_InputField.text;
foreach (DatabaseManager.User user in DatabaseManager.Instance.UserInfos)
{
if (input_name == user.Username)
{
remind_Text.text = "Registration failed! Username already exists!";
return;
}
}
// 检测账号是否重复
string input_account = account_InputField.text;
foreach (DatabaseManager.User user in DatabaseManager.Instance.UserInfos)
{
if (input_account == user.Useraccount)
{
remind_Text.text = "Registration failed! Account already exists!";
return;
}
}
// 当用户输入通过后,添加新用户数据
string input_password = password_InputField.text;
DatabaseManager.User newUser = new DatabaseManager.User(input_name , input_account , input_password);
// 将新用户数据写入MySQL数据库中
DatabaseManager.Instance.InsertNewUserInfo(newUser);
remind_Text.text = "Registration successful!";
Invoke("ClosePanel" , 0.5f);
return;
}
void ClosePanel()
{
this.gameObject.SetActive(false);
}
#endregion
}
登录功能:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Org.BouncyCastle.Asn1.X509;
public class LoginPanel : MonoBehaviour
{
[Header("输入框控件")]
public TMP_InputField account_InputField;
public TMP_InputField password_InputField;
[Header("提示文本")]
public TMP_Text remind_Text;
#region 按钮监听事件
public void onSignInButtonClick()
{
string input_account = account_InputField.text;
string input_password = password_InputField.text;
// 查询账号是否存在
bool isAccountExited = false;
DatabaseManager.User targetUser = new DatabaseManager.User();
foreach (DatabaseManager.User user in DatabaseManager.Instance.UserInfos)
{
if (user.Useraccount == input_account)
{
targetUser = user;
isAccountExited = true;
}
}
if (!isAccountExited)
{
remind_Text.text = "Account does not exist!";
return;
}
// 查询密码是否正确
if (input_password != targetUser.Userpassword)
{
remind_Text.text = "Incorrect password!";
return;
}
else
{
remind_Text.text = targetUser.Username + ", welcome!";
return;
}
}
#endregion
}
进行测试
我们运行程序,可以看到成功读取并储存了数据库表中的用户信息:

随后进行登录测试,可以看到登录功能如期实现:

最后进行注册测试,添加一个用户信息:

(这里UI界面没调好……)
然后打开数据库命令窗口,查询一下是否添加了新的用户:

可以看到,我们成功添加了一个用户!
在过程中你可能遇到的报错及解决建议
| 序号 | 报错信息 | 原因 | 解决方法 |
|---|---|---|---|
| 1 | MySqlException: Authentication method 'caching_sha2_password' not supported |
MySQL 8.0+ 默认认证插件是 caching_sha2_password,旧版驱动不支持 |
① 连接字符串加 SslMode=None;② 或修改用户认证方式为 mysql_native_password |
| 2 | MySqlException: Client does not support authentication protocol requested by server |
同上,驱动版本过旧 | 升级 Connector/NET 到 8.0+,或改用户认证插件 |
| 3 | Assembly 'MySql.Web.dll' will not be loaded due to errors: Unable to resolve reference 'WebMatrix.WebData' |
MySql.Web.dll 是 ASP.NET 专用组件,依赖 System.Web,Unity 不支持 |
删除 MySql.Web.dll,只保留 MySql.Data.dll 及其核心依赖 |
| 4 | Unable to resolve reference 'Google.Protobuf'. Is the assembly missing or incompatible with the current platform? |
Connector/NET 8.0+ 依赖 Google.Protobuf.dll 等库,未复制到 Plugins |
从 Connector/NET 安装目录复制所有依赖 dll 到 Plugins |
| 5 | KeyNotFoundException: The given key 'utf8mb4' was not present in the dictionary. |
Connector/NET 6.x 字符集映射表不包含 utf8mb4 |
连接字符串加 CharSet=utf8; 或升级到 Connector/NET 8.0+ |
| 6 | KeyNotFoundException: The given key 'utf8mb3' was not present in the dictionary. |
同上,6.x 驱动不认识 utf8mb3 |
连接字符串加 CharSet=utf8; 或 CharSet=latin1;,或升级驱动 |
| 7 | MySqlException: You have an error in your SQL syntax... near ''user_name','user_account','user_password') |
列名被单引号包裹,MySQL 将其当作字符串而非列名 | 去掉列名两端的单引号,或改用反引号 ` |
| 8 | ArgumentException: Keyword not supported. Parameter name: sslmode |
旧版 Connector/NET 不支持 SslMode 参数 |
去掉 SslMode=None;,改用修改 MySQL 认证插件的方式 |
| 9 | Assembly 'MySql.Data.dll' will not be loaded due to errors: Reference has errors |
dll 版本不兼容或缺少依赖项 | 检查是否用了正确的 dll 版本(v4.5.2/v4.8),补齐所有依赖 |
| 10 | 'UserInfo' is missing the class attribute 'ExtensionOfNativeClass' |
Unity 尝试序列化普通 C# 类,类名可能与 Unity 内部类冲突 | ① 加 [System.Serializable]② 改为 private class 内部类③ 改类名 ④ 删除 Library 文件夹清理缓存 |
| 11 | MySqlException: There is already an open DataReader associated with this Connection |
一个连接同时只能有一个打开的 DataReader | 执行下一个命令前先 mySqlDataReader.Close() |
| 12 | Unity 一直在 Reloading Domain |
Domain Reload 卡住,常见于静态变量或 DLL 加载问题 | ① 删除 Library 和 Temp 文件夹② 或取消勾选 Reload Domain(Edit → Project Settings → Editor → Enter Play Mode Settings) |
| 13 | MySqlException: Unable to connect to any of the specified MySQL hosts |
网络问题或 MySQL 服务未启动 | ① 检查 MySQL 服务是否运行 ② 检查 IP/端口是否正确 ③ 尝试用 127.0.0.1 替代 localhost |
| 14 | MySqlException: Access denied for user 'root'@'localhost' |
用户名或密码错误 | 确认用户名密码正确,或重置 MySQL 密码 |
| 15 | NullReferenceException: Object reference not set to an instance of an object |
sqlConnection 未初始化,或 DataReader 读取空值 |
检查 builder.ToString() 是否成功,检查数据库是否有数据 |
最后
因本人也是在处于探索阶段,示例的代码、知识点的讲述难免有许多问题(如我是直接直接拼接用户输入来给数据库插入信息,而非参数化查询,这可能会导致数据混乱或泄露),后续通过进一步的学习探索,会进行相关更新。
