読者です 読者をやめる 読者になる 読者になる

ヒキニートがゲームを作るブログ

Unityでゲームを作る過程を投稿します

HPバーの実装【UnityでRTSを作る 11】

Health.csの改良

まずHealthクラスをHPバーで使用できるように改良します。

Health.cs

using System;
using UnityEngine;
using UnityEngine.Events;

[Serializable]
public class HealthEvent : UnityEvent<Health> { }

public class Health : MonoBehaviour {
	
	[SerializeField]
	private int _Value = 100;
	[SerializeField]
	private int _Max = 100;

	[Header("Events")]
	public HealthEvent onValueChanged;
	public HealthEvent onDie;

	public int Value {
		get { return _Value; }
		set {
			_Value = Mathf.Clamp(value,0,Max);
			onValueChanged.Invoke(this);
			if (IsDead) onDie.Invoke(this);
		}
	}

	public int Max {
		get { return _Max; }
		set {
			_Max = Mathf.Clamp(value,1,_Max);
			Value = Value;
		}
	}

	public bool IsDead {
		get { return Value == 0; }
	}

	private void OnValidate () {
		Value = _Value;
		Max = _Max;
	}

}

変更箇所はこんな感じです。

  • 使用するイベントをOnValueChangedEvent(intを引数にする)からHealthEventに変更(Healthを引数にする)
  • Maxプロパティを追加。(HPの割合を求める際に必要)

HPバー実装

ここからHPバーを実装していきます。

UIを組み立てる

f:id:MackySoft:20170506164720j:plain
f:id:MackySoft:20170506164711j:plain

ターゲットを追い続けるUI

オブジェクトの上にHPバーを表示し続けたいので、
UIにターゲットを追わせるためのコンポーネントを用意します。

UIFollwTarget.cs

using UnityEngine;

public class UIFollowTarget : MonoBehaviour {
	
	public Transform target;
	public Vector2 offset;
	private RectTransform rectTransform = null;

	void Awake () {
		rectTransform = GetComponent<RectTransform>();
	}

	void Update () {
		if (!target) return;
		rectTransform.position = RectTransformUtility.WorldToScreenPoint(Camera.main,target.position) + offset;
	}
}

こちらで紹介されているものに少し手を加えたものです。
tsubakit1.hateblo.jp

HPBar.cs

HPバーを操作するためのコンポーネントを用意します。

HPBar.cs

using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(UIFollowTarget))]
public class HPBar : MonoBehaviour {

	public static HPBar Prefab {
		get { return _Prefab ? _Prefab : (_Prefab = Resources.Load<HPBar>("Prefabs/UI/HPBar")); }
	}
	private static HPBar _Prefab = null;
	
	public Image hpBar;
	
	[Header("Color")]
	public bool colorChange = true;
	public Color safetyColor = Color.blue;
	public Color warningColor = Color.yellow;
	public Color dangerColor = Color.red;

	private RectTransform tr;
	private Health health;
	private UIFollowTarget uft;

	public static HPBar Instantiate (Health health) {
		var ins = Instantiate(Prefab,FindObjectOfType<Canvas>().transform);
		ins.Initialize(health);
		return ins;
	}
	
	private void Awake () {
		tr = hpBar.GetComponent<RectTransform>();
		uft = GetComponent<UIFollowTarget>();
	}

	private void Start () {
		if (health) Initialize(health);
	}

	public void Initialize (Health health) {
		uft.target = health.transform;
		health.onValueChanged.AddListener(OnValueChanged);
	}

	public void Disable () {
		health.onValueChanged.RemoveListener(OnValueChanged);
	}

	private void OnValueChanged (Health health) {
		float p = (float)health.Value / (float)health.Max;
		tr.localScale = new Vector3(p,1,1);
		if (colorChange) {
			if (p > 0.5f)
				hpBar.color = safetyColor;
			else if (p > 0.25f)
				hpBar.color = warningColor;
			else
				hpBar.color = dangerColor;
		}
	}
}

主なメンバー

名前 説明
Prefab インスタンス化する際に使うプレハブの参照。
hpBar 増減するバー。
colorChange 色を変化させるかどうか。
Instantiate HPバーのプレハブをインスタンス化する。
Initialize 指定したHealthで初期化する。
Disable プーリングシステムを実装したときに使用したい。
OnValueChanged HealthのValueが変化したときのコールバック。

HPバーを生成

ユニットの拠点の基底クラスのCKWBehaviourに、
HPバーをインスタンス化する処理を実装しました。

CKWBehaviour.cs(重要部分を抜粋)

public abstract class CKWBehaviour : MonoBehaviour {

	protected static bool isQuitting = false;
	
	protected HPBar hpBar = null;

	protected virtual void Start () {
		hpBar = HPBar.Instantiate(Health);
	}

	protected virtual void OnDestroy () {
		if (isQuitting) return;
		Destroy(hpBar.gameObject);
	}
	
	private void OnApplicationQuit () {
		isQuitting = true;
	}

}

動画