C#
Unity
Photon
Unity2017

【PUN】ゲーム終了判定

Photon Unity Networkの基本機能メモ

【PUN】ログイン
【PUN】アバター生成・同期
【PUN】ゲーム終了判定


  • 誰かのHPが0になったときに、そのプレイヤーに死亡フラグを立てて、ゲームオーバーを表示。
  • 同時に全プレイヤーの死亡状態を取得したい。
  • 各プレイヤーの死亡状態はPhotonNetwork.player.SetCustomPropertiesで設定。
  • カスタムプロパティが変更されたタイミングで、PhotonNetwork.playerListをforeachで回してプレイヤーの死亡状態を確認していく。
  • 死亡者が一人以上存在して、生存者が一人だけなら、その生存者が勝者!ゲーム終了

photon.gif

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;
    }

}