Unityの公式チュートリアルに掲載されているマルチプレイヤーネットワーキングを勉強を進めている様子をお送りします。前回の記事はこちらからどうぞ
公式サイトのチュートリアルページ プレイヤーの体力【シングルプレイヤー】
今回のステップではプレイヤーに体力ゲージを追加して弾丸のダメージ処理を行います。
最初は弾丸のプレハブに衝突判定用のコリジョンコンポーネントを追加します。
作成したスクリプトのコードにコメントを加えたものがこちら。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Bullet : MonoBehaviour { // コリジョンと衝突した場合の処理 void OnCollisionEnter() { // オブジェクトを削除 Destroy(gameObject); } }
ここで、ありがちなミスをしてしまいました。
プリミティブオブジェクト Cylinder を使って銃を作成した際に Capsule Collider コンポーネントを削除する手順を忘れていたので、弾が発射されると同時に削除されてしまいました。
修正後、チュートリアルの解説通り、他のオブジェクトに衝突した弾丸は破壊されるようになりました。
プレイヤーの体力値を制御するスクリプトを作成します。
作成したスクリプトのコードにコメントを加えたものがこちら。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Health : MonoBehaviour { // 体力値を格納する変数(定数値 100) public const int maxHealth = 100; // 現在の体力値を格納する変数(初期値は maxHealth) public int currentHealth = maxHealth; // ダメージ処理 public void TakeDamage(int amount) { // 現在の体力値から 引数 amount の値を引く currentHealth -= amount; // 現在の体力値が 0 以下の場合 if (currentHealth <= 0) { // 現在の体力値に 0 を代入 currentHealth = 0; // コンソールに"Dead!"を表示する Debug.Log("Dead!"); } } }
弾丸が衝突した際のダメージ処理をスクリプトの追加します。
作成したスクリプトのコードにコメントを加えたものがこちら。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Bullet : MonoBehaviour { // コリジョンと衝突した場合の処理 void OnCollisionEnter(Collision collision) { // 変数 hit に衝突したオブジェクトを格納 var hit = collision.gameObject; // 変数 healthに、変数 hit に格納されたオブジェクトのコンポーネント Health を格納 var health = hit.GetComponent<Health>(); // 変数 health が空でなければ if (health != null) { // ダメージ処理を実行(体力値-10) //(スクリプト health の関数 TakeDamage を実行) health.TakeDamage(10); } // オブジェクトを削除 Destroy(gameObject); } }
動作確認してみると、10回相手のプレイヤーオブジェクトに弾を当てるとコンソールに Dead! と表示されました。そのまま弾を当て続けると体力値がすでに 0 なので Dead! が続けて表示されます。
体力値を表示するゲージの前景を作成します。
体力値ゲージの前景を作成します。
Foreground の [Inspector]ウィンドウで RectTransform コンポーネントはこのように表示されています。
Foreground を [Scene]ビューで確認するとこのようになっています。
作成した体力ゲージをプレイヤープレハブに組み込みます。
Healthbar Canvas を[Inspector]ウィンドウで確認するとこのようになっています。
体力ゲージの表示処理をスクリプトに追加します。
作成したスクリプトのコードにコメントを加えたものがこちら。
using System.Collections; using System.Collections.Generic; using UnityEngine; // UIコンポーネント関数を使用するため名前空間の追加 using UnityEngine.UI; public class Health : MonoBehaviour { // 体力値を格納する変数(定数値 100) public const int maxHealth = 100; // 現在の体力値を格納する変数(初期値は maxHealth) public int currentHealth = maxHealth; // RectTranform コンポーネントを格納する変数 public RectTransform healthBar; // ダメージ処理 public void TakeDamage(int amount) { // 現在の体力値から 引数 amount の値を引く currentHealth -= amount; // 現在の体力値が 0 以下の場合 if (currentHealth <= 0) { // 現在の体力値に 0 を代入 currentHealth = 0; // コンソールに"Dead!"を表示する Debug.Log("Dead!"); } // RectTranform コンポーネントのサイズを体力値に合わせて変更 //(X値に currentHealth を代入、Y値は RectTranform コンポーネントのY値を代入) healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y); } }
プレハブ Player を選択して [Inspector]ウィンドウで Health コンポーネントはこのように表示されています。
スクリプトコンポーネントのフィールド設定を行います。
体力ゲージが常にメインカメラ方向を向く処理を行うスクリプトを作成します。
作成したスクリプトのコードにコメントを加えたものがこちら。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Billboard : MonoBehaviour { // ゲーム実行中の繰り返し処理 void Update() { // メインカメラの方向に向くようにする transform.LookAt(Camera.main.transform); } }
このステップを終えてゲームを実行。今回はビルドしたゲームを2つ実行してウィンドウを並べました。ゆっくり互いに撃ち合ってみると体力ゲージは変化はほぼ同期しています。
しかし、チュートリアルの解説に書いてある通り、連射すると下図左側のローカル(ホスト)画面と右側のリモート(クライアント)画面で体力ゲージ表示が同期されていないことが確認できます。