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を組み立てる
ターゲットを追い続ける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; } }