在恢复基于Unity Mirror的VR手术模拟器过程中,我们遇到了一系列配置问题。本文详细记录了从发现问题到最终解决的完整过程。
症状表现:
# 客户端日志显示:
Log: [LinkPlayer] ContentIpAndPort() - Target Port: 7111 # 客户端尝试连接7111
# 但服务器实际运行在:
Log: [SERVER] Starting server on port: 7118 # 服务器运行在7118
根本原因:
Unity Inspector中localPort
数组配置错误:
// 错误配置:
localPort[0] = 7111 // ❌ 与服务器端口7118不匹配
localPort[1] = 7112 // ✅ 正确匹配服务器端口
// 服务器配置:
Server 0: Port=7118, SurgeryType=0 // 膝关节手术
Server 1: Port=7112, SurgeryType=1 // 髋关节手术
解决方案:
在Unity Inspector中修正LinkPlayer.cs
的localPort
数组:
// 正确配置:
localPort[0] = 7118 // ✅ 匹配膝关节手术服务器
localPort[1] = 7112 // ✅ 匹配髋关节手术服务器
localPort[2] = 44448
localPort[3] = 55558
症状表现:
修改StreamingAssets中的配置文件不生效,系统依然连接到旧的公网IP。
问题分析:
发现存在两个相同名称但位置不同的配置文件:
StreamingAssets/SeverJSONData.json ← 开发者修改的文件(被忽略)
PersistentDataPath/SeverJSONData.json ← 系统实际读取的文件
配置文件使用规律:
文件 | 客户端使用 | 服务端使用 | 实际作用 |
---|---|---|---|
SeverJSONData.json (PersistentDataPath) | ✅ 是 | ❌ 否 | 客户端IP配置 |
SeverJSONData.json (StreamingAssets) | ❌ 否 | ❌ 否 | 孤立文件! |
ServerData.json (StreamingAssets) | ✅ 是 | ✅ 是 | 房间配置 |
解决方案:
SeverJSONData.json
// 位置:C:/Users/用户名/AppData/LocalLow/项目名/SeverJSONData.json
{
"Ip": "localhost",
"Port": "8080"
}
症状表现:
开发者困惑为什么需要8080端口,以为所有连接都应该直接到游戏端口。
问题分析:
系统实际采用双服务器设计:
服务器类型 | 端口 | 功能 | 提供内容 |
---|---|---|---|
配置服务器 | 8080 | HTTP文件服务 | ServerData.json, Agora.json |
游戏服务器 | 7118/7112 | Unity Mirror游戏 | 实际VR会话 |
工作流程:
客户端启动 → 读取IP配置 → 从8080获取房间列表 → 连接7118/7112游戏服务器
解决方案:
理解配置层次和回退机制:
// 配置获取优先级:
1. 尝试远程:http://IP:8080/ServerData.json (配置服务器)
2. 回退本地:StreamingAssets/ServerData.json (本地文件)
3. 连接游戏:IP:7118 或 IP:7112 (游戏服务器)
// 在Unity Inspector中设置LinkPlayer组件:
Element 0: 7118 // 膝关节手术
Element 1: 7112 // 髋关节手术
Element 2: 44448 // 其他端口
Element 3: 55558 // 其他端口
// 编辑:AppData/LocalLow/项目名/SeverJSONData.json
{
"Ip": "localhost",
"Port": "8080"
}
为了避免依赖外部配置服务器,有三种解决方案:
方案A:强制使用本地文件(推荐)
// 修改RoomButtonHub.cs的Start方法:
void Start()
{
// 强制使用本地文件,跳过web服务器
string surl = ""; // 空URL强制本地回退
string agoraurl = ""; // 空URL强制本地回退
StartCoroutine(UnityWebRead(surl));
StartCoroutine(AgoraWebRequest(agoraurl));
}
方案B:搭建本地配置服务器
# 在StreamingAssets目录下运行:
python -m http.server 8080
方案C:修改配置逻辑
// 在LoadPortFromServerData()中添加本地优先逻辑
if (File.Exists(localPath)) {
// 直接使用本地文件,跳过网络请求
LoadFromLocal(localPath);
}
{
"Ip": "localhost",
"Port": "8080"
}
{
"serverLists": [
{
"PlayerNum": 0,
"IsConnected": 1,
"Port": 7118,
"RoomName": "膝关节手术室",
"IsSurgerySelect": 0,
"RoomId": "knee_room_1"
},
{
"PlayerNum": 0,
"IsConnected": 1,
"Port": 7112,
"RoomName": "髋关节手术室",
"IsSurgerySelect": 1,
"RoomId": "hip_room_1"
}
],
"version": "0.1"
}
❌ 错误:修改 Assets/StreamingAssets/SeverJSONData.json
✅ 正确:修改 AppData/LocalLow/项目名/SeverJSONData.json
❌ 错误:认为8080是游戏连接端口
✅ 正确:8080是配置服务器,7118/7112是游戏端口
❌ 错误:配置服务器必须可用
✅ 正确:系统会自动回退到本地文件
localPort
数组正确设置通过解决这些配置问题,我们成功将一个难以调试的VR系统转换为易于部署和维护的稳定应用。