You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动