Unity 2018连接MySQL完整指南:从环境配置到避坑实战 📅 发布时间:2026/9/15 14:45:44 👁 浏览次数: 如果你已经要用 Unity 连接一次 MySQL那你大概率不是在写单机 Demo。我做游戏后台项目时第一个被要求实现的功能就是Unity 客户端能直接读写数据库里的玩家存档和排行榜。当时 Unity 版本正好卡在 2018网上资料又杂又乱有的说需要第三方插件有的说直接引 DLL 就行我试了一圈踩了无数坑最后才把这条链路彻底跑通。这篇文章我就从 Unity 2018 这个具体版本出发完整拆一遍连接 MySQL 的方案选型、环境配置、代码实现和发布阶段必须避开的坑。适合正在做排行榜、存档同步、数字孪生数据对接或者单纯想搞明白Unity 怎么和数据库打交道的开发者。我先说清楚一个大前提直连 MySQL 更适合局域网内部工具、原型验证和学习阶段公网生产环境建议走中间层 API这个后面会细讲但直连的原理和代码依然是你理解整个数据链路的最好切入点。1. 先说结论这个需求该不该直连 MySQL1.1 直连的场景与门槛很多人一听到Unity 连数据库第一反应是做个登录注册或者排行榜这确实是典型场景。但实际项目里需要这种能力的地方远不止这些。我做过的数字孪生展示项目中Unity 负责接收设备数据、展示三维场景同时要把设备状态和操作记录写到 MySQL还有一些内部运营工具直接用 Unity 做客户端后端就一个 MySQL连管理中心都能省掉。直连 MySQL 的技术门槛其实不高你需要的基础是C# 语法基础、SQL 的增删改查、以及一点网络概念IP、端口、连接字符串。但门槛不高不代表没有坑最大的坑集中在驱动版本、Unity 脚本运行时版本、以及打包平台差异上。尤其是 Unity 2018 这个版本它正好处在 .NET 3.5 到 .NET 4.x 过渡的时期很多人连接失败第一原因就是没切脚本运行时。1.2 三套连接方案对比我为什么选这套Unity 连接 MySQL 成熟方案大致有三类我做了个对比表方便你根据自己项目情况选。方案优点缺点适用场景MySql.Data.dll 官方驱动直连SQL 功能完整、代码直观、能掌握底层原理依赖 DLL 版本、公网部署有安全风险、WebGL 不能用局域网工具、原型验证、学习链路第三方封装库如 UnityMySQL 等API 简单、上手快功能受限、维护不活跃、底层还是包了 MySql.Data简单 Demo 教学HTTP 中间层 UnityWebRequest安全、跨平台、WebGL 也可用需要额外写后端接口、多一次网络请求生产环境、公网、多端我最终选择第一套方案不是因为第二套第三套不好而是因为直连方案能让我在最短时间内验证完整链路Unity 发起查询 → C# 驱动构造 SQL → MySQL 执行 → 结果回传 → UI 展示。这套流程跑通后你对数据流向的认知是完整的以后切换到中间层方案只需要把数据库操作挪到服务端Unity 侧改成发 HTTP 请求思路几乎不用变。1.3 Unity 2018 版本的特殊性Unity 2018 是个分水岭。从 2018 版本开始Unity 加入了 .NET 4.x Equivalent 脚本运行时的支持这意味着你可以使用较新版本的 MySql.Data 驱动。如果你新建项目后不动设置默认还是 .NET 3.5 Equivalent那 MySql.Data 8.0 版本会在运行时直接抛一堆 TypeLoadException很多新手在这个坑里卡一整天。所以第一步必须去 Player Settings 里把 Scripting Runtime Version 切成 .NET 4.x Equivalent。如果项目确实古老没法切那就只能退而求其次用老驱动 MySql.Data 6.9.x。我的建议是新项目直接用 Unity 2018.4 LTS .NET 4.x MySql.Data 8.0.x 这套组合社区里验证过的人最多遇到问题也最好查。2. 环境准备Unity 工程和 MySQL 两边都要动2.1 Unity 工程侧配置不切运行时会翻车先打开 Unity 2018创建或打开项目后依次点击 Edit → Project Settings → Player → Other Settings找到 Configuration 区域。这里有两个关键下拉框Scripting Runtime Version 和 Api Compatibility Level。Scripting Runtime Version 必须选 .NET 4.x Equivalent。这一步是大多数教程不会强调的但恰恰是成败的关键。选完之后 Unity 会提示需要重启编辑器照着做就行。Api Compatibility Level 同样要选 .NET 4.x不要选 .NET Standard 2.0因为部分 MySql.Data 版本对 Standard 2.0 的支持并不完整在打包阶段容易出幺蛾子。为什么这两个配置这么重要因为 MySql.Data 8.0 官方要求最低 .NET Framework 4.5.2Unity 2018 的 .NET 3.5 Equivalent 运行时压根不满足这个条件。如果你不切换就算 DLL 导入成功编译能过运行时也会在实例化连接对象时立刻报错。我见过最典型的报错是 TypeLoadException: Could not load type System.Threading.Tasks.Task from assembly mscorlib就是这个原因。2.2 MySQL 服务端配置账号、权限、监听地址一步都不能少MySQL 服务端安装本身不复杂社区版下载安装选 Server only设置好 root 密码即可。但要注意安装完成后默认的 bind-address 是 127.0.0.1也就是说 MySQL 只监听本机回环地址Unity 客户端在另一台机器或局域网内是永远连不上的。修改方法找到 MySQL 配置文件 my.iniWindows或 my.cnfLinux在 [mysqld] 段落下添加或修改这行bind-address 0.0.0.0保存后重启 MySQL 服务。这行配置的意思是让 MySQL 监听所有网络接口而不是只监听本地。改完之后还需要确认 Windows 防火墙是否放行了 3306 端口如果没放行外部连的时候会直接超时。如果用的是云服务器还需要在安全组规则里放行 3306。接下来是账号和权限。千万不要直接用 root 账号给 Unity 用风险太大。正确姿势是创建专用账号只给必要的库和必要的权限。我用到的 SQL 如下CREATE DATABASE IF NOT EXISTS game_db DEFAULT CHARACTER SET utf8mb4; CREATE USER unity_user% IDENTIFIED BY 这里换成你自己的强密码; GRANT SELECT, INSERT, UPDATE, DELETE ON game_db.* TO unity_user%; FLUSH PRIVILEGES;这里的 % 表示允许来自任意主机的连接如果只在局域网用更稳妥的方式是限制网段比如 unity_user192.168.1.%。权限方面只给了 SELECT、INSERT、UPDATE、DELETE没给 DROP、CREATE 这类危险权限这个习惯要从一开始就养成。配置完成后建议先用 MySQL Workbench 或 Navicat 验证一下用 unity_user 连接数据库试试能否查询。这一步能提前把服务端配置问题排除掉免得后面写完了 Unity 代码才发现根本不是代码的问题。2.3 DLL 导入细节几个版本坑一次说清驱动文件是连接的关键通常用 MySql.Data.dll。获取方式有两种Visual Studio 里通过 NuGet 安装 MySql.Data 包或者直接到官网下载 .NET Connector。我推荐在 Visual Studio 里建一个空项目NuGet 安装 MySql.Data 8.0.x然后从 packages 目录里把 net45 或 netstandard2.0 版本的 MySql.Data.dll 复制出来。复制出来后放到 Unity 项目的 Assets/Plugins 文件夹下。放在这个目录下的 DLL 会被 Unity 当作原生插件处理打包时会自动包含脚本也可以直接 using。但这里有几个细节要注意。第一MySql.Data 8.0 不是单文件依赖它可能依赖 System.Buffers、System.Memory、Google.Protobuf 等如果只复制主 DLL运行时可能报找不到程序集。稳妥的做法是打开 NuGet 包目录把 net45 目录下所有 dll 一起复制到 Plugins。如果服务端是 MySQL 5.6 或 5.7我反而推荐用老一点的 MySql.Data 6.9.12这个版本依赖极少对 Unity 2018 兼容性也更好。第二如果项目里已经存在其他版本的 MySql.Data或者有第三方插件自带了这个 DLL一定要清理掉否则会报程序集冲突错误信息类似 Assembly MySql.Data has different version than expected。我在项目里就遇到过和某个广告 SDK 冲突的情况最后是删除重复 DLL 才解决。第三判断 DLL 是否导入成功可以在 Unity 的 Project 窗口选中 DLL看 Inspector 底部会显示平台兼容情况或者写一行代码测试Debug.Log(typeof(MySql.Data.MySqlClient.MySqlConnection).FullName)。如果能打印出完整类型名说明驱动已经可用。3. 核心代码实现从查询到写入3.1 连接字符串详解每个参数都得知道干嘛的连接字符串是 Unity 和 MySQL 之间唯一的通信地址格式如下string connectionString Server192.168.1.100;Port3306;Databasegame_db;Uidunity_user;Pwdyour_password;CharSetutf8mb4;SslModenone;Connection Timeout5;;逐个参数说下参数含义示例ServerMySQL 服务器 IP 或主机名192.168.1.100PortMySQL 端口默认 33063306Database要连接的数据库名game_dbUid登录用户名unity_userPwd登录密码你自己设的密码CharSet字符集影响中文存取utf8mb4SslModeSSL 模式局域网可设 nonenoneConnection Timeout连接超时秒数5SslMode 这里特别说一句MySQL 8.0 服务端默认开启 SSL 支持部分客户端驱动在 SSL 握手上有些玄学问题直接连局域网时经常白白消耗时间。我实测下来内网环境设 SslModenone 能显著缩短握手时间并且不影响功能。如果后续要公网上用那另说局域网内用 none 是没问题的。Connection Timeout 我也建议显式设置。Unity 客户端最怕卡死如果不设超时一旦服务器不可达数据库操作会阻塞很久配合后面讲的异步处理这个参数能确保快速失败。3.2 查询方法从 MySQL 拉数据到 Unity UI接下来是重头戏写一个简单的数据库访问类。我习惯把连接字符串写在私有字段里后续所有数据库操作都走这个类的方法。最基础的查询代码如下using MySql.Data.MySqlClient; using System; using System.Collections.Generic; using UnityEngine; public class MySqlHelper { private string connectionString Server192.168.1.100;Port3306;Databasegame_db;Uidunity_user;Pwdyour_password;CharSetutf8mb4;SslModenone;Connection Timeout5;; public ListPlayerData GetTop10Players() { ListPlayerData result new ListPlayerData(); string sql SELECT id, nickname, score FROM player ORDER BY score DESC LIMIT 10;; using (MySqlConnection conn new MySqlConnection(connectionString)) { conn.Open(); using (MySqlCommand cmd new MySqlCommand(sql, conn)) { using (MySqlDataReader reader cmd.ExecuteReader()) { while (reader.Read()) { PlayerData data new PlayerData(); data.id reader.GetInt32(id); data.nickname reader.GetString(nickname); data.score reader.GetInt32(score); result.Add(data); } } } } return result; } } public class PlayerData { public int id; public string nickname; public int score; }这里有几个细节。using 语句一定要用MySqlConnection 和 MySqlDataReader 都是非托管资源不释放会导致连接池耗尽后面会专门讲这个坑。读取字段时用 GetInt32(id) 这种按列名读取的方式比 reader[0] 可读性更强也不容易因为 SELECT 语句顺序变化而出错。如果只想快速看结果可以做个 UI 绑定测试。在场景里创建一个 Text 组件查询后把结果拼接成字符串赋给 Text.text。看到玩家数据在游戏界面里显示出来的那一刻这条链路就算通了后面所有复杂功能都是在这个基础上扩展。3.3 写入方法参数化 SQL 是底线别用字符串拼接写入数据的核心除了正确还要安全。很多人在教学 Demo 里写这样的 SQLstring sql INSERT INTO player (nickname, score) VALUES ( nickname , score );这种写法必须严令禁止。一方面存在 SQL 注入风险用户输入特殊字符就能改变 SQL 语义另一方面如果 nickname 里带了单引号这条 SQL 直接语法错误。正确做法是用参数化查询public void InsertPlayer(string nickname, int score) { string sql INSERT INTO player (nickname, score) VALUES (nickname, score);; using (MySqlConnection conn new MySqlConnection(connectionString)) { conn.Open(); using (MySqlCommand cmd new MySqlCommand(sql, conn)) { cmd.Parameters.AddWithValue(nickname, nickname); cmd.Parameters.AddWithValue(score, score); cmd.ExecuteNonQuery(); } } }AddWithValue 这个方法会自动处理类型转换和转义单引号、反斜杠都不会破坏 SQL 结构。更新操作同理UPDATE 语句里也全部走参数化。如果你要循环插入大量数据比如批量导入配置表逐条执行会非常慢。简单优化方案是用事务包裹或者拼接批量 SQL。我常用的是事务方式using (MySqlConnection conn new MySqlConnection(connectionString)) { conn.Open(); MySqlTransaction transaction conn.BeginTransaction(); try { foreach (var item in playerList) { string sql INSERT INTO player (nickname, score) VALUES (nickname, score);; using (MySqlCommand cmd new MySqlCommand(sql, conn, transaction)) { cmd.Parameters.AddWithValue(nickname, item.nickname); cmd.Parameters.AddWithValue(score, item.score); cmd.ExecuteNonQuery(); } } transaction.Commit(); } catch { transaction.Rollback(); throw; } }事务的好处是一旦中间某条失败之前所有插入都回滚不会留下半截脏数据。3.4 用协程或异步避免卡死主线程不能阻塞前面所有代码都是同步执行这在编辑器里跑没问题在真机上跑就会暴露问题数据库操作是网络 IO耗时可能是几百毫秒如果 Unity 主线程被阻塞游戏画面会直接卡住。尤其是移动端用户点一下按钮界面转圈好几秒体验非常差。Unity 的主线程是渲染线程同时负责处理 MonoBehaviour 生命周期方法你不应该把耗时的网络操作直接丢在主线程。解决办法是用 Task.Run 把数据库操作放到线程池再用协程轮询完成状态回到主线程更新 UI。public class RankPanel : MonoBehaviour { public Text rankText; public void OnShowRankButtonClick() { StartCoroutine(LoadRankData()); } private IEnumerator LoadRankData() { MySqlHelper helper new MySqlHelper(); ListPlayerData result null; string error null; bool done false; Task.Run(() { try { result helper.GetTop10Players(); } catch (Exception e) { error e.Message; } finally { done true; } }); yield return new WaitUntil(() done); if (error ! null) { rankText.text 加载失败: error; } else if (result ! null) { StringBuilder sb new StringBuilder(); foreach (var player in result) { sb.AppendLine(player.nickname : player.score); } rankText.text sb.ToString(); } } }这里 WaitUntil 会每帧检查 done 标志位一旦子线程跑完协程继续执行此时已经回到了主线程可以安全地操作 UI。Unity 2018 在切到 .NET 4.x 后也支持 async/await 写法但如果你对线程上下文不熟悉我建议先用协程方案思路更直白更适合 Unity 项目。等协程跑顺了再尝试把数据库服务封装成异步接口也不迟。4. 打包发布前必须知道的坑4.1 IL2CPP 下的兼容性问题提前验证再上Unity 2018 打包 Android 或者 iOS 时脚本后端可以选择 Mono 或 IL2CPP。真机和主流应用商店对包体大小和性能有要求IL2CPP 更常见但它也是直连 MySQL 时最容易翻车的环节。IL2CPP 的工作方式是把 C# 代码转换成 C再编译成平台原生代码。这个过程对反射和动态代码生成支持有限而 MySql.Data 的老版本驱动里恰好用了不少反射和动态类型判断逻辑。打包后运行到数据库相关代码时可能会直接抛异常常见报错有 ExecutionEngineException 或者 NotSupportedException。我的建议是如果项目只是开发阶段验证打包到 Windows 用 Mono 就够了如果确定要发 Android 且必须用 IL2CPP开工前先建一个只包含数据库查询的最小工程用 IL2CPP 打包到真机跑一次确认驱动兼容性。实测下来MySql.Data 8.0 在大多数 Android 设备上能跑但偶尔也会碰到机型相关的问题根本原因还是 IL2CPP 对某些 API 不友好这种问题往往无处可查最后只能换方案。如果直连在目标平台实在跑不通别死磕退回到 HTTP 中间层方案。Unity 这边用 UnityWebRequest 请求后端接口数据库操作全部在后端完成打包到任何平台都没问题。4.2 移动端和 WebGL 的差异性不是所有平台都能直连Android 和 iOS 上直连 MySQL除了 IL2CPP 问题还要注意网络权限。Android 需要在 AndroidManifest.xml 里声明 INTERNET 权限Unity 一般默认会带但如果你改了 Manifest 文件一定要手动检查。iOS 上如果走的是 HTTP 而非 HTTPS还要在 Info.plist 里处理 App Transport Security 设置。WebGL 平台则基本不要指望直连。浏览器运行环境是沙箱机制JavaScript 没有能力直接建立原始 TCP 连接MySql.Data 压根无法在浏览器里工作。之前有朋友做 WebGL 版本的游戏直连失败后卡了很久最后用了 WebSocket 代理服务中转。这个思路可行但复杂度远高于直接改 HTTP 中间层方案。热搜词里有个 unity 发布 webgl 使用 idbfs 写入失败这跟数据库其实没关系是浏览器文件系统的问题但它和直连 MySQL 失败一样都说明 WebGL 平台有很多边界限制。我的经验是新的项目如果准备发 WebGL从一开始就不要往数据库直连方向设计直接把数据访问层设计成 HTTP API 形态省得后面推倒重来。4.3 数据安全与防护客户端写死密码等于裸奔Unity 客户端直连数据库最大的问题不在技术而在安全。打包出来的游戏容易被反编译C# 代码配合 dnSpy 或 ILSpy 这类工具直接可以看到字符串常量你写在连接字符串里的数据库密码相当于明文暴露。之前我做过一个离线的项目密码就直接写在代码里后来被要求给客户做个内部演示版我特意把连接字符串抽到了外部配置文件虽然也谈不上绝对安全但至少比硬编码强。对于生产环境更彻底的方案是客户端完全不接触数据库Unity 只调用后端接口数据库密码只存在于服务端环境变量里。除了密码问题日常开发还要注意几点数据库账号权限要最小化不要给 Unity 账号 DROP 或 ALTER 权限所有输入必须参数化查询结果要校验类型DataReader 里某字段为 NULL 时强行 GetString 会抛异常用 IsDBNull 判断一下更稳。这些习惯不是洁癖是帮你省掉线上事故的保障。5. 常见问题排查我踩过的雷都在这5.1 连接失败的逐层排查清单连接数据库失败是最常见的问题报错千奇百怪但排查路径是固定的。我从近到远整理了一个排查清单遇到问题按顺序走一遍大部分都能解决。现象可能原因排查方法Unable to connect to any of the specified MySQL hostsMySQL 没监听外部地址、防火墙拦截、IP 不通先 ping 服务器再用 telnet IP 3306 测端口检查 bind-address 和防火墙Access denied for user unity_user...账号不存在、密码错误、host 不允许在 MySQL 里用 SQL 查看账号确认 host 范围和密码Unknown database game_db数据库没创建或名字写错Workbench 里确认库名注意大小写Connection Timeout网络不通、端口被挡、连接字符串配置错误先用 Workbench 在同一网络环境下测试连接Authentication method not supportedMySQL 8.0 默认认证插件与驱动不兼容详见下一节最经典的现象是本机 MySQL Workbench 能连上Unity 却连不上。这种情况九成是 bind-address 没改或防火墙没放行。用 netstat -an 查看 3306 端口监听地址如果显示 127.0.0.1:3306 而不是 0.0.0.0:3306那就是配置没生效。5.2 MySQL 8.0 认证插件不兼容一行 SQL 搞定如果你用的是 MySQL 8.0 服务端而驱动是 MySql.Data 6.9.x 或更老的版本连接时会报这样的错误Authentication method caching_sha2_password not supported by any of the available plugins。原因很简单MySQL 8.0 默认的认证插件是 caching_sha2_password而老版驱动只认识 mysql_native_password。解决办法是给 Unity 用户改回旧认证方式ALTER USER unity_user% IDENTIFIED WITH mysql_native_password BY your_password; FLUSH PRIVILEGES;执行完这行再连接就通了。如果是新项目直接用 MySql.Data 8.0 版本驱动天然支持新认证插件就不需要改。5.3 中文乱码字符集不一致的锅Unity 读出来的中文显示成问号或者乱码原因通常是字符集没统一。MySQL 默认字符集可能是 latin1而 Unity 的字符串是 UTF-8两者转换出了问题。我的做法是统一三处字符集数据库、表、连接字符串。建库时指定 utf8mb4CREATE DATABASE IF NOT EXISTS game_db DEFAULT CHARACTER SET utf8mb4;连接字符串里加上 CharSetutf8mb4。如果用的老驱动不支持 utf8mb4就改成 CharSetutf8。注意如果存储时就已经是乱码光改连接字符串救不回来得先清理数据再从源头保证字符集。排查乱码问题有个技巧先用 Workbench 直接查询表里数据。如果 Workbench 显示正常说明库里数据没问题是 Unity 读取时解码错误重点查连接字符串如果 Workbench 显示也乱说明写入时就错了得检查写入方和表结构。5.4 连接资源耗尽你忘了释放连接做 Unity 客户端最容易忽略的问题就是连接释放。早前我做测试时反复打开关闭界面某次突然报 Too many connections一看 MySQL 最大连接数 151全被占满了。原因就是连接对象没释放。MySqlConnection 是托管对象但它内部持有底层 socket靠垃圾回收不可靠必须手动 release。正确做法是每个连接都用 using 包裹如下面这样using (MySqlConnection conn new MySqlConnection(connectionString)) { conn.Open(); // 执行操作 }using 语句会在作用域结束时自动调用 Dispose连接会归还连接池而不是真正关闭后续复用成本很低。如果你用了异步操作还要注意每次查询都 new MySqlConnection不要复用一个已关闭的旧连接容易踩到连接状态异常。连接池参数也可以在连接字符串里调比如加 Poolingtrue;Connection Lifetime30让池里的连接合理回收。总之内存泄漏可以靠工具查连接泄漏就只能靠代码习惯防。最后再分享点个人经验这套直连方案我前前后后用了半年多后来项目规模变大稳定性和安全性要求上来最终我把数据库操作收拢到了后端服务Unity 客户端只通过 HTTP 接口拿数据。但回头看直连 MySQL 这段经历非常值钱它让我彻底搞懂了连接字符串、SQL 执行、数据流传输的完整链路后续用中间层方案时很多后端接口设计都是在直连代码基础上改出来的。如果你也想自己动手跑一遍我的建议是不要一上来就设计复杂的数据库结构先建一张 player 表字段就 id、nickname、score把 SELECT 和 INSERT 跑通再逐步扩展到更新、事务、异步。这个最小闭环走通了后面所有扩展都只是加 SQL 语句而已。Unity 2018 连接 MySQL 不是个能用花哨技巧绕过去的问题它是客户端工程师和数据库打交道的第一道门槛跨过去之后你会发现整个外部系统接入的思路都通了。