【PUN】ゲーム終了判定


Photon Unity Networkの基本機能メモ

[【PUN】ログイン](https://qiita.com/mo4_9/items/4aba4601feb3e6440826)
[【PUN】アバター生成・同期](https://qiita.com/mo4_9/items/75324cc31709ec329d26)
[【PUN】ゲーム終了判定](https://qiita.com/mo4_9/items/87b969da060c975736cf)

---

- 誰かのHPが0になったときに、そのプレイヤーに死亡フラグを立てて、ゲームオーバーを表示。
- 同時に全プレイヤーの死亡状態を取得したい。
- 各プレイヤーの死亡状態は[PhotonNetwork.player.SetCustomProperties](https://doc-api.exitgames.com/en/pun/current/class_photon_player.html#af8815abb8edaafbe6bddbf328f9612fb)で設定。
- カスタムプロパティが変更されたタイミングで、[PhotonNetwork.playerList](https://doc-api.exitgames.com/en/pun/current/group__public_api.html#ggaf30bbea51cc8c4b1ddc239d1c5c1468fa67402d95c324cda2b6d6e2fc391ae941)をforeachで回してプレイヤーの死亡状態を確認していく。
- 死亡者が一人以上存在して、生存者が一人だけなら、その生存者が勝者！ゲーム終了

![photon.gif](https://qiita-image-store.s3.amazonaws.com/0/136286/c56863d2-ad61-242d-7b59-795ae4e221c4.gif)

```csharp:Avatar.cs
using UnityEngine;
using System.Collections;
using System.Linq;
using UnityEngine.UI;

public class Avatar : Photon.MonoBehaviour {

	[SerializeField] int m_healthPoint = 100;
	[SerializeField] GameObject m_BulletPrefab;
	[SerializeField] GameObject m_DamageEffectPrefab;

	PhotonView m_photonView;

	void Start() {
		m_photonView = GetComponent<PhotonView> ();
		if(m_photonView.isMine) {
			// 初期設定
			SetPlayerName ("Player-Id: " + PhotonNetwork.player.ID);
			SetPlayerDeathState (false);
			SetHealthPoint (m_healthPoint);
		}
	}

	void SetPlayerName(string name) {
		this.gameObject.name = name;
		transform.Find ("NameUI").gameObject.GetComponent<TextMesh> ().text = name;
	}

	void SetHealthPoint(int num) {
		m_healthPoint = num;
		transform.Find ("HealthPointUI").gameObject.GetComponent<TextMesh> ().text = num.ToString();
	}

	// ストリーム同期
	void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {
		if (stream.isWriting) {
			// 自分の情報を送る
			string myName = this.gameObject.name;
			int myHealthPoint = m_healthPoint;
			stream.SendNext (myName);
			stream.SendNext (myHealthPoint);
		} else {
			// 他人の情報を受け取る
			string otherName = (string)stream.ReceiveNext();
			int otherHealthPoint = (int)stream.ReceiveNext();
			SetPlayerName (otherName);
			SetHealthPoint (otherHealthPoint);
		}
	}

	// イベント同期
	[PunRPC]
	void Shoot(Vector3 i_pos, Vector3 i_angle) {
		Quaternion rot = Quaternion.Euler (i_angle);
		GameObject bullet = GameObject.Instantiate (m_BulletPrefab ,i_pos ,rot);
		bullet.GetComponent<Rigidbody> ().AddForce (transform.forward * 20, ForceMode.VelocityChange);
		Destroy(bullet, 3);
	}

	void OnTriggerEnter(Collider i_other) {
		if(i_other.tag == "bullet"){
			// ダメージを受ける
			SetHealthPoint (m_healthPoint - 10);
			Instantiate (m_DamageEffectPrefab, transform.position, Quaternion.identity);
			Destroy (i_other.gameObject);

			if(m_healthPoint <= 0){
				if (m_photonView.isMine) {
					SetPlayerDeathState (true);
					string text = "You Lose...";
					DrawResult(text, new Color(0f,0f,1f));
				}
			}
		}
	}

	void Update () {

		if(m_photonView.isMine == false){
			return;
		}

		if (Input.GetKeyDown (KeyCode.Space)) {
			// 自分自身の弾丸でトリガーを引かないようにやや手前から発射
			Vector3 pos = transform.position + transform.forward * 2f;
			Vector3 angle = transform.eulerAngles;
			// 処理が重いのでPhotonViewを付けずに位置と角度を渡す
			m_photonView.RPC ("Shoot", PhotonTargets.AllViaServer, pos, angle);
		}

		// キーボード入力による移動処理
		var v = Input.GetAxis ("Vertical");
		Vector3 velocity = new Vector3 (0, 0, v);
		velocity = transform.TransformDirection (velocity);
		velocity *= 5f;
		transform.localPosition += velocity * Time.fixedDeltaTime;

		// キーボード入力による回転処理
		var h = Input.GetAxis ("Horizontal");
		transform.Rotate (0, h * 3f, 0);
	}
    
    // ===============================
    // ここから重要
    // ===============================
	public void SetPlayerDeathState( bool isDeath ) {
		var properties  = new ExitGames.Client.Photon.Hashtable();
		properties.Add ("player-id", PhotonNetwork.player.ID);
		properties.Add ("isDeath", isDeath);
		PhotonNetwork.player.SetCustomProperties( properties );
	}

	public void OnPhotonPlayerPropertiesChanged( object[] i_playerAndUpdatedProps ){
		// 全員分回す
		var aliveList = new ArrayList();
		var deathList = new ArrayList();
		foreach(var p in PhotonNetwork.playerList) {
			Debug.Log ("player-id : " + p.CustomProperties["player-id"].ToString() + " - " + "isDeath : " + p.CustomProperties["isDeath"].ToString());
			if ((bool)p.CustomProperties ["isDeath"]) {
				deathList.Add (p);
			} else {
				aliveList.Add (p);
			}
		}
		if(aliveList.Count == 1 && deathList.Count > 0) {
			var winner = (PhotonPlayer)aliveList[0];
			var winnerId = winner.CustomProperties["player-id"];
			if((int)PhotonNetwork.player.ID == (int)winnerId) {
				string text = "プレイヤー" + winnerId.ToString() + " の勝利";
				DrawResult(text, new Color(1f,0f,0f));
			}
		}
	}

	void DrawResult(string text, Color color) {
		Text ResultText = GameObject.Find("ResultText").GetComponent<Text>();
		ResultText.text = text;
		ResultText.color = color;
	}

}
```