将UI画布同步到光子网络| PunRPC

问题描述

我有一个问题,无法将UI Canvas信息同步到PhotonNetwork。如果没有Photon,它可以很好地同步,并且在调试时可以获得正确的信息。但是,如果我以光子开始,它将无法同步。

以下代码

void Start()
{
    PV = GetComponent<PhotonView>();
    Debug.Log("I kNow who is :  " + PV);
}



 void Update()
{

    PV.RPC("displayHP",RpcTarget.All);
    displayHP();

    Shoottest();
    Debug.Log("Player HP : " + playerHP);

}


}
[PunRPC]
void displayHP()
{
  if(PV.Ismine)
    {
        showHP.text = playerHP.ToString();
    }      
         
}
  

}

我可能以错误的方式使用它,有人可以说明我在这里做错了什么吗?这只是“健康画布”中的一个示例,其他画布的行为也与“健康画布”完全相同。

下面的完整脚本:

[Serializefield] float playerHP = 100f;
[Serializefield] TextMeshProUGUI showHP;  
[Serializefield] AudioClip audioClip;


public int armorCheck;
public int energyCheck;
float energyBack = 25;
//public PhotonView PV;


void Start()
{
   // PV = GetComponent<PhotonView>();
    
}

public void EnergyPot()
{
    //if(PV.Ismine)
    //{
        Ammo currentAmmo = GetComponent<Ammo>();
        int energyCheck = GetComponent<Ammo>().GetCurrentAmmo(AmmoType.EnergyDrink);

        if (energyCheck > 0)
        {
            playerHP = energyBack + playerHP;
            if (playerHP >= 100)
            {
                playerHP = 100;
                currentAmmo.ReduceCurrentAmmo(AmmoType.EnergyDrink);

            }
        }
    //}                
}
public void Takedamage(float damage)
{
 //   if (PV.Ismine)
 //{ 
        Ammo currentAmmo = GetComponent<Ammo>();
    int armorCheck = GetComponent<Ammo>().GetCurrentAmmo(AmmoType.Armor);
    if (armorCheck <= 0)
    {
        playerHP -= damage;
        if (playerHP <= 0)
        {
            GetComponent<DeathHandler>().HandleDeath();
            AudioSource.PlayClipAtPoint(audioClip,Camera.main.transform.position);
            GetComponent<Animator>().SetTrigger("Dead_Player");
        }
    }
    else
    {
        currentAmmo.ReduceCurrentAmmo(AmmoType.Armor);
    }
  }
//}
//public void OnPhotonSerializeView(PhotonStream stream,PhotonMessageInfo info)
//{
//    if(stream.IsWriting)
//    {
//        //displayHP();
//        stream.SendNext(playerHP);
//    }
//    else if (stream.IsReading)
//    {
//        //displayHP();
//        playerHP = (float)stream.ReceiveNext();
//    }

//}

 void Update()
{                
    displayHP();
    Shoottest();        
}

void Shoottest()
{
    if (Input.GetMouseButtonDown(0))
    {
        GetComponent<Animator>().SetBool("Shoot_Player",true);
        // GetComponent<Animator>().SetTrigger("ShootPlayer");
    }
   // GetComponent<Animator>().SetBool("Shoot_Player",false);
}

void displayHP()
{
    //if(PV.Ismine)
    //{
        showHP.text = playerHP.ToString();            
        //Debug.Log("PV works under displayHP,code  :  " + PV);
        Debug.Log("Player HP : " + playerHP);
    //}            
             
}

}

解决方法

您仅同步少参数的方法调用,从而更新显示。.但是,您从未更新要显示的信息:playerHP

PhotonView.RPC使用方法名称RpcTarget,然后根据需要/方法期望选择任意多个参数。

void Start()
{
    PV = GetComponent<PhotonView>();
    Debug.Log("I know who is :  " + PV);
}

private void Update()
{
    if(PV.IsMine)
    {
        ShootTest();
        Debug.Log("Player HP : " + playerHP);
    }
}

// only executed every 0.2 seconds to reduce traffic
void FixedUpdate()
{
    if(PV.IsMine)
    {
        // pass in the value to sync
        PV.RPC(nameof(DisplayHP),RpcTarget.Others,playerHP);
        DisplayHP(playerHP);
    }
}

[PunRPC]
void DisplayHP(float hp)
{
    // receive the synced value if needed 
    playerHP = hp;
    showHP.text = hp.ToString();
}

实际上,为避免出现更多的冗余网络流量,您应该使用property,它会在显示更改时自动更新显示,并且仅在playerHP实际更改时发送远程呼叫,例如

[SerializeField] private float _playerHP;

private float playerHP
{
    get => _playerHP;
    set
    {
        _playerHP = value;
        showHP.text = playerHP.ToString();

        if(PV.IsMine)
        {
            // sync the change to others
            PV.RPC(nameof(RemoteSetHP),_playerHP);      
        }
    }
}

[PunRPC]
void RemoteSetHP(float hp)
{
    // this executes the setter on all remote players
    // and thus automatically also updates the display
    playerHP = hp;
}

所以无论何时设置

playerHP = XY;

它会自动更新显示,如果是您的光子视图,它会将远程呼叫发送给其他人,并更新值并在那里显示。

,

除了我的评论外,这是一个示例。假设您的HP和其他玩家HP有Text。首先,您通过调用UpdateHP方法来更改您的HP,为您的HP更新Text并将RPC发送给其他人,这会更新其客户端上的otherHp(因为您在他们的计算机上将是“ other”)您对HP的新价值。

public Text myHpText;
public Text otherHpText;

void UpdateHp(int hp)
{
    myHpText.text = hp.ToString();

    PV.RPC("UpdateOtherText",myHp);
}

[PunRPC]
void UpdateOtherText(int hp)
{
    otherHpText.text = hp.ToString();
}