Unity 网络就绪检查

Unity Networked Ready check

尝试使用 PUN2 创建就绪检查,以便所有玩家同时加载到游戏场景中,但我不明白如何检查另一个玩家自定义 属性 并计算如何许多玩家目前已经准备就绪,如果所有人都准备好了,那么就开始游戏吧。我想我已经为每个应该设置的玩家设置了一个自定义 属性,但我不确定它是否有效。

 public class HeroSelectController : MonoBehaviour
 {
     [HideInInspector]
     public string selectedHero;

     private PhotonView PV;
     private bool PlayerReady = false;
     private ExitGames.Client.Photon.Hashtable _playerCustomProperties = new ExitGames.Client.Photon.Hashtable();

     private void Update()
     {
         Debug.Log("Player Ready = " + _playerCustomProperties["PlayerReady"]);
     }

     private void HeroSelect()
     {
         PlayerReady = true;    
         selectedHero = "PlayerTest";
         PhotonNetwork.SetPlayerCustomProperties(_playerCustomProperties);
         _playerCustomProperties["PlayerReady"] = PlayerReady;
     }

     public void OnClickHeroButton()
     {
         HeroSelect();

         if (PhotonNetwork.IsMasterClient)
         {
             foreach (var photonPlayer in PhotonNetwork.PlayerList)
             {
                 photonPlayer.CustomProperties["PlayerReady"] = true;
                 PhotonNetwork.LoadLevel(3);
             }
         }

     }
 }

目前的情况是主客户端可以开始游戏,而不管其他人的状态如何。感觉我可能想得太多了,并且有一个非常相似的解决方案,因为我希望这样的功能很常见,因为我希望在许多在线游戏中使用类似的东西,所以如果我完全错了请指点一个更合适的方向

不知道 Photon 的确切工作原理,但我假设这些属性已经同步,据我了解,您只是想要某种检查,例如

private bool AllPlayersReady
{
    get
    {
        foreach (var photonPlayer in PhotonNetwork.PlayerList)
        {
            if(photonPlayer.CustomProperties["PlayerReady"] == false) return false;
        }

        return true;
    }
}

您也可以使用 Linq 来缩短

using System.Linq;

...

private bool AllPlayersReady => PhotonNetwork.PlayerList.All(player => player.CustomProperties["PlayerReady"] == true);

然后像这样使用它

public void OnClickHeroButton()
 {
     HeroSelect();

     if (!PhotonNetwork.IsMasterClient) return;

     if(!AllPlayersReady)
     {
         return;
     }


     PhotonNetwork.LoadLevel(3);
 }

这仍然可以加强,因为现在主人必须反复按下,直到每个人都准备好了。我还会使用 Coroutine like

public void OnClickHeroButton()
{
     HeroSelect();

     if (!PhotonNetwork.IsMasterClient) return;

     StartCoroutine (WaitAllReady ());   
 }

 private IEnumerator WaitAllReady()
 {
     yield return new WaitUntil (() => AllPlayersReady);

     PhotonNetwork.LoadLevel(3);
 }

感谢 Iggy:

您可以使用 OnPlayerPropertiesUpdate 来检查就绪状态,而不是检查每一帧的例程

void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
{
    if (!PhotonNetwork.IsMasterClient) return;

    // you can even limit the check to make it 
    // only if "PlayerReady" is among the changed properties
    if(!changedProps.Contains("PlayerReady")) return;

    if(!AllPlayersReady) return;

    PhotonNetwork.LoadLevel(3);
}

注意:在智能手机上打字,但我希望思路清晰