今回はプレイヤーが操作するキャラクターの上にログイン画面で入力した名前の表示をするようにし、どのキャラクターを誰が操作しているのかわかるようにします。
また、あらかじめ敵を数体配置しておき、プレイヤーが敵を攻撃した時のダメージを与える処理を作成していきます。
前回まででプレイヤーキャラクターをネットワーク上に登場させるところまでをやりました。
まだ機能を作成していない方は参照してプレイヤーキャラクターを登場させるようにしてください。
キャラクターの頭の上に名前を表示させる
まずはプレイヤーキャラクターの頭の上にログイン時に入力した名前を表示させるようにしていきます。
キャラクターの子要素にUIを作成
Ethanの子要素にUI→Canvasを作成し名前をName、その子要素にUI→Textを作成します。
↑のようにNameが設置されました。
次にNameのインスペクタのCameraのRender ModeをWorld Spaceにし普通のゲームオブジェクトと同じような表示方法にします。
↑のように変更し、ScaleとY座標を調整しキャラクターの頭上にちょうどよい大きさのテキストとなるようにします。
↑が実際のNameのテキストの大きさです。
キャラクターの名前を設定するスクリプトの作成
キャラクターの名前は自身のキャラクターだけでなく他のキャラクターの名前も表示しなければいけません。
つまりネットワークごしに他のプレイヤーのキャラクターにも名前を送信し設定しなければいけません。
とりあえずそこら辺は後回しにしてキャラクターに名前を設定するスクリプトOperationNameを作成しEthanに取りつけます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | using UnityEngine; using System.Collections; using UnityEngine.UI; public class OperationName : MonoBehaviour { private GameObject namePlate; // 名前を表示しているプレート public Text nameText; // 名前を表示するテキスト void Start() { namePlate = nameText.transform.parent.gameObject; } void LateUpdate() { namePlate.transform.rotation = Camera.main.transform.rotation; } void SetName(string name) { nameText.text = name; } } |
LateUpdateメソッドで名前が常にカメラの向きになるようにしています。
なぜLateUpdateで行っているかというと名前はキャラクターの子要素になっていてキャラクターを動かすと同じ向きに名前も回転しますが、
LateUpdateで名前をカメラの向きにすればキャラクターの移動を考慮した後に名前をカメラの向きにしてその後描画されるのでちゃんと表示されます。
LateUpdateに関しては
を参照してください。
EthanにこのOperationNameスクリプトを取りつけてインスペクタで名前のTextを設定します。
SetNameメソッドが呼ばれればこのキャラクターの名前が設定されますが、あくまでこれはオフラインでの処理です。
その為、ネットワークを介して接続しているキャラクターのSetNameを呼び出し自身のキャラクターと他の人のキャラクターそれぞれに名前を設定しなければいけません。
ネットワークを介して他のプレイヤーのスクリプトのメソッドを呼び出すにはRPC(Remote Procedure Calls)を使用します。
このRPC機能ですがUnityのNetwork機能を使う場合は古いやり方となっており、現在は別のやり方でネットワーク処理をするみたいです。
PhotonCloudではRPCの代わりにPunRPCを使ったやり方で従来の方式と同じです。
まずはネットワークごしに呼ばれるSetNameにPunRPCアトリビュートを設定します。
1 2 3 4 5 6 | [PunRPC] void SetName(string name) { nameText.text = name; } |
メソッドの前に[PunRPC]という文字列を入れます。
JavaScriptの場合は@PunRPCです。
余談ですが、
JavaScriptでネットワーク対応するのを途中でやめた理由はこの[PunRPC]や@PunRPCが認識されなかった為です。
そこら辺はアセンブリの参照の仕方とかの影響があるんだと思いますが、わたくしには解決出来なかったのでC#で記述する事にしました・・・・(-_-)
後はキャラクターが登場した時にこのSetNameを呼び出せばいいことになります。
キャラクターを登場させているのはNetworkManagerスクリプトのSetPlayerメソッドなのでそこを修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // 部屋に入室した時に呼ばれるメソッド public override void OnJoinedRoom() { loginUI.SetActive(false); logoutButton.SetActive(true); Debug.Log("入室"); // InputFieldに入力した名前を設定 if (playerName.text != "") { PhotonNetwork.player.NickName = playerName.text; } else { PhotonNetwork.player.NickName = "DefaultPlayer"; } // プレイヤーキャラクターを登場させる StartCoroutine("SetPlayer", 0f); } // プレイヤーをゲームの世界に出現させる IEnumerator SetPlayer(float time) { yield return new WaitForSeconds(time); // ネットワークごしにEthanをインスタンス化する player = PhotonNetwork.Instantiate("Ethan", Vector3.up, Quaternion.identity, 0); player.GetPhotonView().RPC("SetName", PhotonTargets.AllBuffered, PhotonNetwork.player.NickName); } |
OnJoinedRoomメソッドで名前入力欄が空じゃなければその名前を設定し、空だった場合は『DefaultPlayer』という名前を設定します。
SetPlayerメソッドではネットワークごしに生成したキャラクターのPhotonViewをGetPhotonViewで取得しRPCを使ってSetNameメソッドを呼び出しています。
この場合EthanにPhotonViewとPunRPCが記述されたSetNameメソッドを持つスクリプトが設定されている必要があります。
第2引数では送る相手を指定していて、PhotonTargets.AllBufferedを指定すると全ての接続キャラクターに送られます。
AllBufferedだとバッファにも保存されるので後から接続してきたキャラクターの他のキャラクターの名前も設定されることになります。
第3引数はSetNameメソッドに渡す引数で実際に設定する名前ですね。
これでキャラクターの名前を頭上に表示する機能が完成しました。
ここまでのEthanは↑のように設定されています。
複数のアプリケーションを実行し自分のキャラクター、他の人のキャラクターの名前が設定されている事を確認しましょう。
↑のように自身のキャラクターの頭上に名前が表示され、後から接続してきたプレイヤーキャラクターの名前も表示されています。
AllBufferedなので後から接続してきたプレイヤー『abc』が接続すると、前から接続してプレイヤーキャラクター『DefaultPlayer』の名前も設定されています。
敵に攻撃しダメージを与え倒す
ネットワークごしにRPCを使って他のプレイヤーのメソッドを呼び出す事が出来るようになりました。
そこでゲーム内にあらかじめ敵を用意しておき、敵にダメージを与えたり倒したりといったことをネットワークごしに行えるようにします。
敵キャラクターは
↑のように設定されています。
今回の敵キャラクターは特に動かして同期させる事はしないのでPhotonViewのObserved Componentには何も設定していません。
それでは敵キャラクターのダメージ処理をしているEnemyスクリプトを改造し、RPCに対応するようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | using UnityEngine; using System.Collections; public class Enemy : Photon.PunBehaviour { private int hp; // 敵の体力 void Start () { hp = 10; } [PunRPC] void Damage(int damage) { Debug.Log("敵に" + damage + "ポイント与えた"); this.hp -= damage; if(this.hp <= 0) { Dead(); } } void Dead() { if (photonView.isMine) { Debug.Log ("敵を倒した"); PhotonNetwork.Destroy (gameObject); } } } |
EnemyはPhoton.PunBehaviourを継承する形にします。
Damageメソッドには[PunRPC]アトリビュートを設定しネットワークごしに呼べるようにします。
Deadメソッドではこの敵キャラクターが自身のゲーム内で出現させたかどうかを判定しネットワークごしにDestroyをしてゲームオブジェクトを削除します。
敵を攻撃し確認する
敵を攻撃しネットワークごしにダメージを与える処理が出来たので確認してみます。
↑のようにネットワークで敵キャラクターのダメージを与え、倒した時は別プレイヤーのアプリケーションでも敵が消えるようになりました。
終わりに
ネットワークを介して別のプレイヤーキャラクターの名前を表示したり、敵キャラクターにダメージを与えた時に他のプレイヤーのスクリプトのメソッドを呼び出したりして、
マルチプレイをさせる時の処理が実現出来ました。
細かい作りこみの部分では全然ちゃんとしてはいないですが、マルチプレイを実現させる為ことははある程度出来たのではないかと思います。
これで協力プレイは出来るようになりましたが、キャラクター同士で攻撃を出来るようにしてオンラインでの対戦ゲームも作れると思います。
今回でPhoton Cloudを使ったオンラインマルチプレイ対応は終了となります。