问题描述
我有一个问题,无法将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();
}