おっさんプログラマのUnity奮闘記

元WEB系プログラマのUnity奮闘記

おっさんのUnity入門 2Dオブジェクトでスコアを実装する(プレファブとUIの連携)

敵オブジェクトが量産できるようになりましたので、撃破ポイントをスコアとして表示するUIを実装します。

【追加・修正するオブジェクト】
  • EnemyStatus.cs(敵オブジェクトの状態管理用スクリプト)[修正]
  • UIControllder.cs(UIオブジェクトの管理用スクリプト)[修正]
  • CanvasWrapper/Canvas/ScoreText(スコア表示用テキストオブジェクト)[追加]
【スコア用UIオブジェクトの追加】

Hierachy→Create→UI→TextでテキストオブジェクトをCanvas直下に追加します。
UI text additional image

任意の位置・フォントの大きさ・フォントの色を指定します。
UI text adjustment image

UI text adjustment image by Inspector

【実装する機能(敵オブジェクト側(プレファブ))】
  • 敵自身が保持している撃破ポイントをUIオブジェクト側に渡す機能
  • UI表示更新ロック制御機能
【実装する機能(UIオブジェクト側)】
  • 撃破ポイントを格納するリスト
  • 撃破ポイントリストへ敵オブジェクト側から受け取った値を追加する機能
  • 撃破ポイントスコア表示機能
  • 撃破ポイントスコア表示更新機能
  • 撃破ポイントリストの外部呼出しをロックする機能(ほぼ同時に撃破した際に処理が衝突することを防止するため)

【EnemyStatus.cs(敵オブジェクトステータス管理スクリプト)】

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyStatus : MonoBehaviour {

	// 敵の体力の入れ物
	// Inspectorで設定
	[SerializeField]
	private int enemyArmorPoint;

	// 撃破したときに受け取れるポイント
	// Inspectorで設定
	[SerializeField]
	private int enemyDestroyPoint;

	// Canvasの入れ物
	Canvas canvas;
	// UIControllerの入れ物
	UIController uicontroller;

	// 撃破時にUIControllerの撃破ポイントリスト呼び出し判定フラグ
	// falseなら呼び出し可
	private bool isActiveScore;

	void Start () {
		// 敵の体力を初期化
		//enemyArmorPoint = 3;

		// UIControllerを取得する
		// canvasを取得してからそのコンポーネントであるスクリプトを
		// 取得する
		canvas = GameObject.Find ("CanvasWrapper")
			.GetComponentInChildren<Canvas>();
		uicontroller = canvas.GetComponent<UIController> ();
		// UIControllerから撃破ポイントリスト呼び出し可能状態を取得
		isActiveScore = uicontroller.isActiveScoreUpdate;
	}


	// 弾オブジェクトと接触したときに呼び出される関数
	void OnCollisionEnter2D (Collision2D collision) {
		// もしもtagがbulletであるオブジェクトと接触したら
		if (collision.gameObject.tag == "bullet") {
			// 敵の体力が0以上だったら
			if (enemyArmorPoint > 0) {
				// 敵の体力を1削る
				enemyArmorPoint -= 1;
			} else {
				// 敵の撃破スコア更新が可能な状態の場合
				if (isActiveScore == false) {
					// 処理の衝突を防ぐためのisActiveScoreをロック
					uicontroller.isActiveScoreUpdate = true;
					// UIController側から上書きしたisActiveScoreの値を取得
					isActiveScore = uicontroller.isActiveScoreUpdate;
					// ロックが有効になっているか確認
					Debug.Log ("isActiveScoreUpdate : " + isActiveScore);
					// 反映されたisActiveScoreを取得
					isActiveScore = uicontroller.isActiveScoreUpdate;
					// 撃破ポイントリストに撃破ポイントを追加
					// 敵オブジェクト側では整数を渡すだけ
					uicontroller.EnemyDestroyPointListUpdate = enemyDestroyPoint;
					// ロックの解除
					uicontroller.isActiveScoreUpdate = false;
					// UIController側から上書きしたisActiveScoreの値を取得
					isActiveScore = uicontroller.isActiveScoreUpdate;
					// ロックが解除されているか確認
					Debug.Log ("isActiveScoreUpdate : " + isActiveScore);
					// 敵の体力が0になったら敵オブジェクトを消滅させる
					Destroy (gameObject);
				}
			}
		}
	}


}

【UIController.cs(UIオブジェクト管理スクリプト)】

/* UIControllder.cs */

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq; // リストの合計処理のために追加

public class UIController : MonoBehaviour {

	// gameoverTextオブジェクトの入れ物
	Text gameover_text;

	// PLAYERとENEMYの接触状態を表すフラグ
	// get/setメソッドで他のスクリプトから呼び出すためprivateにしておく
	private bool enemyTouch;

	// armorTextオブジェクトの入れ物
	Text armorText;
	// PlayerStatus.csの入れ物
	PlayerStatus player_status;
	// PLAYERの体力の入れ物
	private int armorPoint;

	// 撃破ポイントの入れ物
	private int DestroyPoint;
	// scoreTextオブジェクトの入れ物
	Text scoreText;
	// 敵の撃破ポイントの入れ物
	//private int EnemyDestroyPoint;
	// 敵の撃破ポイントの一時保管用リスト
	private List<int> EnemyDestroyPointList = new List<int> ();
	// 敵の撃破ポイント呼び出し状態フラグ
	// trueの時は撃破ポイント制御関数の呼び出しを待機状態にする
	private bool isActiveScore;
	// 敵の撃破ポイント制御関数内で使用するカウンタ
	private float timeOut = 0.5f;
	private float timeCount;


	void Start () {
		// PlayerStatusの取得
		player_status = GameObject.Find ("PLAYER_GREEN")
			.GetComponentInChildren<PlayerStatus>();
		// PLAYERの体力をPlayerStatus.csのArmorPointから取得して初期化
		armorPoint = player_status.ArmorPoint;
		// armorPointを初期化する
		armorText = GameObject.Find ("armorText").GetComponent<Text> ();
		armorText.text = "armorPoint : " + armorPoint.ToString ();

		// UIのテキストを取得する(gameoverTextへ代入する)
		gameover_text = GameObject.Find ("gameoverText").GetComponent<Text> ();

		// ゲームスタート時はgameoverTextを非表示にしておく
		gameover_text.enabled = false;

		// PLAYERとENEMYの接触状態を表すフラグをfalseに初期化
		enemyTouch = false;

		// UIのテキストを取得する(scoreTextへ代入する)
		scoreText = GameObject.Find("scoreText").GetComponent<Text>();
		// 敵の撃破ポイントを初期化
		DestroyPoint = 0;
		// 撃破ポイントリスト呼び出し判定フラグを初期化
		isActiveScore = false;
		// 撃破ポイントの初期化
		DestroyPoint = 0;
		// 撃破ポイントリストを空にする
		EnemyDestroyPointList.Clear();
		// 敵の撃破ポイント制御関数内で使用するカウンタの初期化
		timeCount = 0;

	}
	

	void Update () {
		// PLAYERとENEMYが接触したら
		if (enemyTouch == true) {
			// PLAYERの体力を更新する
			armorPoint = player_status.ArmorPoint;
			// PLAYERの体力表示を更新する
			armorText.text = "armorPoint : " + armorPoint.ToString ();
		}

		if (armorPoint == 0) {
			// ゲームオーバー表示をするための関数を呼び出す。
			GameOverMessage ();
		}

		// 敵の撃破ポイントスコア表示更新用カウンタ
		// 0.5秒になったら0.0秒にリセットされる
		timeCount += Time.deltaTime;
		if (isActiveScore == false) {
			// 0.5秒毎に更新する
			// 0.5秒以内ならば敵の撃破ポイントリストの追加のみ処理する
			// 敵の撃破ポイントリストの追加は敵オブジェクト側から制御する
			if (timeCount >= timeOut) {
				// 敵の撃破スコアを更新する関数の呼び出し
				ScoreMessage ();
				// timeCountが0.5秒になったら0.0秒にリセットされる
				timeCount = 0.0f;
			}
		}

		// 撃破ポイントリスト格納状態確認関数呼び出し
		//DestroyPointValue (EnemyDestroyPointList);
	}


	// 他のスクリプトから読み書きするための関数
	// 他のスクリプトから呼び出せるようにpublic属性を付ける
	// true/falseを呼び出し元のスクリプトへ渡すためbool型を付ける
	public bool EnemyTouch {
		get { return enemyTouch; }
		set { enemyTouch = value; }
	}


	// ゲームオーバー表示のためのフラグコントロール関数
	void GameOverMessage () {
		gameover_text.enabled = true;
	}


	// 敵の撃破ポイントリスト呼び出し状態判定フラグ更新関数
	public bool isActiveScoreUpdate {
		get { return isActiveScore; }
		set { isActiveScore = value; }
	}

	// 敵を撃破したポイントを制御する関数
	void ScoreMessage () {
		// 敵の撃破ポイントリストの合計値を取得
		int totalDestroyPoint = EnemyDestoryPointSum ();
		// 敵の撃破ポイントリストを空にする。
		EnemyDestroyPointListClear ();
		// 敵の撃破ポイントを加算する
		DestroyPoint = DestroyPoint + totalDestroyPoint;
		// UIの撃破スコアを更新する
		scoreText.text = "Score : " + DestroyPoint.ToString ();
	}

	// 敵の撃破ポイントリストの合計値を返す関数
	public int EnemyDestoryPointSum () {
		return EnemyDestroyPointList.Sum ();
	}

	// 敵の撃破ポイントリストを初期化する関数
	void EnemyDestroyPointListClear () {
		EnemyDestroyPointList.Clear ();
	}

	// 敵の撃破ポイントリスト更新関数
	// 加算のみ行うため整数型を受け取り関数無いで加算する
	public int EnemyDestroyPointListUpdate {
		set { EnemyDestroyPointList.Add (value); }
	}


	// 敵の撃破ポイントリスト確認関数
	void DestroyPointValue (List<int> EnemyDestroyPointList) {
		int i;
		for (i = 0; i < EnemyDestroyPointList.Count; i++) {
			Debug.Log ("[" + i + "] = " + EnemyDestroyPointList [i]);
		}
	}

}

【敵オブジェクトの耐久力と撃破ポイントを指定】

プレファブ内の敵オブジェクトRED_ENEMYを選択してInspectorを表示します。
Enemy Armor Point と Enemy Destroy Point に任意の整数値を入力します。
Image changing durability and destroy points installed in the prefab in the Inspector

【動作確認】

Image of operation confirmation and debugging
Inspectorで指定した値がScoreに加算されるようになりました。
Consoleではロックが実行されている様子が確認できました。



次回は、敵プレファブのバリエーションを増やしてスクリプトの使いまわしを試します。


【参考にさせていただいたサイト】

qiita.com