Unity使用Photon Networking连接自托管专用服务器报错排查
你遇到的报错核心是调用JoinRandomRoom时,Photon客户端还未完成与Master服务器的握手流程,处于ConnectingToMasterServer中间状态,无法执行匹配操作。代码中存在以下几个直接导致该问题的错误:
1. 核心错误:Unity生命周期方法拼写错误
你代码中定义的private void strart()方法存在拼写错误,正确的Unity启动生命周期方法为Start()(首字母大写,拼写为start而非strart)。这个错误会导致游戏启动时你写的连接Master服务器的逻辑完全不会执行,所有连接操作只会在点击匹配按钮时才第一次触发,后续逻辑没有足够的时间完成连接握手。
2. 状态判断逻辑错误
你使用PhotonNetwork.IsConnected判断是否可以执行匹配操作是不准确的:IsConnected仅代表底层网络连接建立完成,不代表Photon已经完成和Master服务器的身份校验、版本校验等握手流程,此时执行JoinRandomRoom就会触发你遇到的报错。
3. 重复连接风险
你在点击匹配按钮的逻辑中,如果检测到未连接就直接调用ConnectToMaster,没有判断当前是否已经处于连接中状态,重复发起连接会导致客户端状态混乱,延长连接完成时间甚至连接失败。
4. 游戏版本设置时机错误
GameVersion是Photon连接Master服务器时的必要校验参数,你只在匹配按钮的未连接分支中设置该参数,启动时的连接逻辑根本没有设置版本,会导致版本校验失败无法完成连接。
5. 无效序列化属性
你给const常量GameVersion加了[SerializeField]属性,const是编译时常量,无法在Unity inspector中序列化显示,该属性属于无效代码。
完整修复代码
[SerializeField] private GameObject FindOppenentTxt = null; [SerializeField] private GameObject waitingStatusPanel = null; [SerializeField] private Text waitingStatusText = null; private bool isConnecting = false; // 修正拼写错误:原变量名多写了一个n private const string GameVersion = "1.1"; // 移除无效的SerializeField属性 private const int maxPlayer = 2; private string masterServerAddress = "**********"; private int port = 7777; private string appID = "*************7d645e794534"; private void Awake() { PhotonNetwork.AutomaticallySyncScene = true; } private void Start() // 修复方法名拼写错误 { PhotonNetwork.SendRate = 20; PhotonNetwork.SerializationRate = 5; PhotonNetwork.GameVersion = GameVersion; // 提前设置游戏版本 PhotonNetwork.ConnectToMaster(masterServerAddress, port, appID); } public void FindOpponent() { // 防止重复点击重复触发逻辑 if (isConnecting) return; isConnecting = true; FindOppenentTxt.SetActive(false); waitingStatusPanel.SetActive(true); waitingStatusText.text = "Searching..."; // 用IsConnectedAndReady判断是否可以执行匹配操作 if(PhotonNetwork.IsConnectedAndReady) { PhotonNetwork.JoinRandomRoom(); Debug.Log("findingRoom"); } else { Debug.Log("Not connected to master, try to connect first"); // 仅当未处于连接中状态时才发起新连接 if (PhotonNetwork.NetworkClientState != ClientState.ConnectingToMasterServer) { PhotonNetwork.GameVersion = GameVersion; PhotonNetwork.ConnectToMaster(masterServerAddress, port, appID); } } } public override void OnConnectedToMaster() { Debug.Log("Server IP: " + PhotonNetwork.ServerAddress); // 加入大厅后再执行匹配,稳定性更高 PhotonNetwork.JoinLobby(); } public override void OnJoinedLobby() { if(isConnecting) { PhotonNetwork.JoinRandomRoom(); } } public override void OnDisconnected(DisconnectCause cause) { waitingStatusPanel.SetActive(false); FindOppenentTxt.SetActive(true); isConnecting = false; // 断开连接时重置匹配状态 Debug.Log($"disconnected, reason: {cause}"); } public override void OnJoinRandomFailed(short returnCode, string message) { Debug.Log("There are no available rooms, creating new room"); PhotonNetwork.CreateRoom(null, new RoomOptions { MaxPlayers = maxPlayer }); } public override void OnJoinedRoom() { Debug.Log("Joined a room successfully"); int playerCount = PhotonNetwork.CurrentRoom.PlayerCount; if(playerCount != maxPlayer) { waitingStatusText.text = "waiting for an opponent"; } else { waitingStatusText.text = "Opponent Found...please wait.."; } } public override void OnPlayerEnteredRoom(Player newPlayer) { if (PhotonNetwork.CurrentRoom.PlayerCount == maxPlayer) { PhotonNetwork.CurrentRoom.IsOpen = false; waitingStatusText.text = "opponent in room"; PhotonNetwork.LoadLevel("MainScene"); } }
内容的提问来源于stack exchange,提问作者Suraj Sharma

