Unity Photon PUN非主客户端GameOver RPC空引用异常求助
问题定位与修复方案
核心问题
非主客户端执行Gameover RPC时,GameManager.cs第360行的score.player.NickName触发空引用异常,本质是非主客户端的score.player引用为null。
触发原因
- 数据同步缺失:
PlayerScore中的player(PhotonPlayer对象)仅在主客户端本地初始化,未通过Photon RPC或PhotonView同步到非主客户端,导致非主客户端无法获取有效引用。 - 对象生命周期问题:游戏结束时,部分玩家对象已被提前销毁,
score.player指向已释放的内存地址。
修复方案
方案1:直接存储玩家昵称,避免依赖PhotonPlayer引用
修改PlayerScore类,不再持有PhotonPlayer引用,而是直接存储昵称字符串:
public class PlayerScore { public string NickName { get; private set; } public int Score { get; private set; } public PlayerScore(string nickName, int score) { NickName = nickName; Score = score; } }
主客户端在收集分数时直接获取玩家昵称并封装到PlayerScore,再通过RPC同步整个列表,非主客户端直接读取NickName字段即可,彻底规避空引用风险。
方案2:通过ActorNumber同步玩家信息
在Gameover RPC中,传递玩家的ActorNumber而非完整PlayerScore对象,非主客户端根据ActorNumber查找有效PhotonPlayer:
// 主客户端调用RPC photonView.RPC("RPC_Gameover", RpcTarget.All, PhotonNetwork.PlayerList.Select(p => p.ActorNumber).ToArray(), playerScores.Select(s => s.Score).ToArray()); // GameManager中的RPC方法 [PunRPC] private void RPC_Gameover(int[] actorNumbers, int[] scores) { for (int i = 0; i < actorNumbers.Length; i++) { PhotonPlayer player = PhotonNetwork.PlayerList.FirstOrDefault(p => p.ActorNumber == actorNumbers[i]); if (player == null) { Debug.LogWarning($"未找到ActorNumber为{actorNumbers[i]}的玩家"); continue; } // 使用player.NickName和scores[i]进行后续逻辑 } }
方案3:添加空引用防御检查(快速临时修复)
在访问score.player.NickName前添加空判断,避免异常抛出:
// GameManager.cs第360行修改 if (score != null && score.player != null) { string playerNick = score.player.NickName; // 原有逻辑 } else { Debug.LogWarning("跳过无效的玩家分数条目"); }
内容的提问来源于stack exchange,提问作者Finalbi
相关产品推荐
相关产品推荐

