PUN 2自定义属性读写问题:团队分配逻辑异常求助
问题分析与解决方案
你遇到的核心问题是直接修改Photon Player的CustomProperties字典不会生效——Photon的CustomProperties是一个只读的缓存视图,必须通过官方提供的SetCustomProperties方法来更新属性,这样才能同步到本地和网络其他玩家。
为什么你的代码没生效?
你这段代码里直接给player.CustomProperties["team"]赋值的操作,只会修改本地的临时字典副本,不会触发Photon的属性同步机制,也不会真正更新服务器上存储的玩家属性。所以后续遍历的时候,那些玩家的team属性其实还是初始的spectator,看起来就像没被分配一样。
修改后的完整代码
下面是修复后的TeamBalance协程,关键是用SetCustomProperties来更新属性:
using ExitGames.Client.Photon; // 记得引入这个命名空间,Hashtable在这里 private IEnumerator TeamBalance() { // 计算需要的天使数量,用FloorToInt确保是整数 angelCount = Mathf.FloorToInt(PhotonNetwork.PlayerList.Length * angelPercent); currentAngels = angelCount; // 随机选取天使 for (int i = 0; i < angelCount;) { int index = Random.Range(0, PhotonNetwork.PlayerList.Length); PhotonPlayer targetPlayer = PhotonNetwork.PlayerList[index]; // 先检查玩家是否有team属性,避免KeyNotFoundException if (targetPlayer.CustomProperties.TryGetValue("team", out object teamValue) && teamValue.ToString() == "spectator") { // 使用SetCustomProperties更新属性,这是Photon官方推荐的方式 targetPlayer.SetCustomProperties(new Hashtable { { "team", "angel" } }); i++; } } // 把剩余观众转为玩家队 foreach (var player in PhotonNetwork.PlayerList) { if (player.CustomProperties.TryGetValue("team", out object teamValue) && teamValue.ToString() == "spectator") { player.SetCustomProperties(new Hashtable { { "team", "player" } }); } } yield return null; }
额外注意事项
初始化玩家属性:确保每个玩家加入房间时,默认就有
team属性设为spectator,可以在OnJoinedRoom方法里做初始化:public override void OnJoinedRoom() { // 初始化自己的team属性为spectator PhotonNetwork.LocalPlayer.SetCustomProperties(new Hashtable { { "team", "spectator" } }); }属性同步监听:如果需要在属性变化时更新本地UI或逻辑,可以重写
OnPlayerPropertiesUpdate方法:public override void OnPlayerPropertiesUpdate(PhotonPlayer targetPlayer, Hashtable changedProps) { if (changedProps.ContainsKey("team")) { string newTeam = changedProps["team"].ToString(); Debug.Log($"{targetPlayer.NickName} 加入了 {newTeam} 队"); // 这里可以添加更新UI、角色状态等逻辑 } }权限控制:建议让房主(Master Client)来执行队伍分配逻辑,避免多个客户端同时修改属性导致冲突:
// 在需要触发分配的地方判断 if (PhotonNetwork.IsMasterClient) { StartCoroutine(TeamBalance()); }
这样修改后,玩家的队伍属性就能正确更新并同步,剩余的观众也会被分配到玩家队了。
内容的提问来源于stack exchange,提问作者Jack Sebben




