今回はUnityでライフゲージの作成をしたいと思います。
以前に敵のHPを敵の頭上に表示する機能を作成しましたが、

今回は主人公キャラクターのHPを前面のUIにアイコンを使って表示します。
アイコンだけだとアイコン一個単位での増減しか出来ないので、それとは別にライフゲージを減らしていく方法もやってみます。
UIの表示領域や設定等はゲーム画面サイズに合わせて調整してください。
アイコンを使ったライフゲージ
まずはアイコン一個単位でライフの増減をする機能を作成していきます。
この機能を作成すると、
上のような感じになります。
Ethanをマウスで押すと1ダメージを与えるようにしています。
アイコンは
を使用していきます。
わたくしが作った物なのでご自由にお使いください(デスクトップ等にドラッグ&ドロップ、または画像を右クリックから名前を付けて保存)。(._.)
Unityにライフゲージアイコンをドラッグ&ドロップしておきます。
インスペクタで
上のように設定します。
Alpha is Transparencyにチェックを入れアルファを透明にします。
今回のアイコンの場合はハートの部分以外の白色をアルファとしているのでその部分が透けます。
またWrap ModeをClampにしアイコンが繰り返し描画されないようにします。
ライフゲージ表示領域の作成
ライフゲージアイコンを表示する領域を作成していきます。
ヒエラルキー上で右クリックからUI→Panelを選択します。
UIのPanelを選択することでCanvasがなければ一緒に作成されPanelはその子要素になります。
Panelを選択した状態でPanelの四隅の三角形のアイコンをShiftキーを押しながらドラッグして下のような範囲を作成します。
Panelの縦はCanvasの5%にしました。
このPanelの子要素にライフゲージアイコンをライフの数だけ表示しますが、アイコンを綺麗に横並びにする為にPanelにHorizontal Layout Groupを設定し自動でアイコンが整列するようにします。
Panelを選択した状態でインスペクタのAdd ComponentからLayout→Horizontal Layout Groupを選択し、以下のような設定にします。
PaddingのLeftを5にしPanelの領域の左側から5ピクセル開けます。
Spacingを1にしてPanelの子要素のライフゲージアイコン同士の間を1ピクセル開けます。
Child Controls SizeとChild Force Expandのチェックを外します。
これは領域の大きさによってアイコンの大きさを拡大したりさせない為にチェックを外しています。
アイコンプレハブの作成
次はライフゲージ表示領域に表示するアイコンプレハブを作成していきます。
Panelを選択した状態で右クリック→UI→Raw Imageを選択し、名前をLifeGaugeとします。
上のような階層になりました。
LifeGaugeを選択し、Rect TransformのWidthとHeightを20にし、Raw ImageのTextureに先ほど取り込んだライフゲージアイコン用のテクスチャを設定します。
現時点では以下のような感じでアイコンが表示されているはずです。
試しにLifeGaugeを選択した状態でCtrl+Dキーを押すとLifeGaugeがコピーされ、親のPanelのHorizotal Layout Groupによってアイコンが勝手に整列されます。
上のような感じですね。
コピーしたLifeGaugeは削除して1個の状態に戻したらLifeGaugeをAssetsエリア内にドラッグ&ドロップしてLifeGaugeをプレハブにします。
プレハブにしたらヒエラルキー上のLifeGaugeオブジェクトは削除します。
LifeGaugeをプレハブにしたのはスクリプトからライフの数だけライフゲージアイコンのプレハブをインスタンス化して表示する為です。
ライフゲージアイコン操作スクリプトの作成
Panelに新しくLifeGaugeスクリプトを作成し取り付けます。
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 30 31 32 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class LifeGauge : MonoBehaviour { // ライフゲージプレハブ [SerializeField] private GameObject lifeObj; // ライフゲージ全削除&HP分作成 public void SetLifeGauge(int life) { // 体力を一旦全削除 for (int i = 0; i < transform.childCount; i++) { Destroy(transform.GetChild(i).gameObject); } // 現在の体力数分のライフゲージを作成 for (int i = 0; i < life; i++) { Instantiate<GameObject>(lifeObj, transform); } } // ダメージ分だけ削除 public void SetLifeGauge2(int damage) { for (int i = 0; i < damage; i++) { // 最後のライフゲージを削除 Destroy(transform.GetChild(i).gameObject); //Destroy(transform.GetChild(transform.childCount - 1 - i).gameObject); } } } |
lifeObjにはインスペクタで先ほど作成したLifeGaugeプレハブを設定します。
SetLifeGaugeメソッドは引数として残りのHPを受け取ります。
transform.childCountでこのスクリプトが設定されているPanelの子要素の数を取得出来るので子要素の数だけDestroyを使って子要素を削除していきます。
Panelの子要素にはライフゲージアイコンのプレハブであるLifeGaugeがHPの数だけ並んでいるので、最初のfor文で一括で削除します。
次のfor文でHPの数だけInstantiateメソッドを使ってLifeGaugeプレハブをインスタンス化し、親要素をtransform(このスクリプトが設定されているPanel)にします。
SetLifeGaugeメソッドだとライフゲージアイコンを一旦全部削除してからHP分を再作成しています。
ライフゲージアイコンの数を多く表示する場合は処理が遅くなりそうなので、別のやり方としてSetLifeGauge2メソッドを作成しました。
こちらの方は引数として受けたダメージを受け取り、そのダメージ数分をPanelの子要素から削除します。
コメント化しているDestroyは子要素の最後の要素から削除していますが、最初から削除しても見た目的に変わらなかったのでこちらはコメントにしました。
これでライフゲージアイコン操作スクリプトは完成しましたが、これらの処理は主人公キャラクターがダメージを受けた時等に呼び出します。
サンプルの主人公キャラの作成
ライフゲージアイコンの機能は出来ましたが、実際に機能を確認する為に主人公キャラクターを作成し、主人公がダメージを受けた時にSetLifeGaugeメソッドを呼び出して実行してみたいと思います。
その為、スタンダードアセットのEthanのモデルをヒエラルキー上にドラッグ&ドロップし、Add ComponentからPhysics→CharacterControllerを選択し取り付けます。
上のようにCharacterControllerのコライダのサイズを調整します。
今回はEthanが押された時にダメージを受けたとして、Ethanに取り付けたダメージ処理スクリプトからLifeGaugeスクリプトの処理メソッドを呼び出してライフゲージアイコンの操作をすることにします。
Ethanが押された時にダメージを与える処理
Ethanに取り付けたコライダ上でマウスボタンが押されたかどうかを判定する為に、Main CameraのAdd ComponentからEvent→Physics Raycasterを取り付けます。
上のようになります。
これでマウスボタンをEthan等のコライダ上で押すとイベントが発生し、そのイベントを受け取ることが出来るようになりました。
イベント受け取りスクリプトをEthanに取り付けマウスボタンが押された時にEthanにダメージを与えるようにします。
Ethanに新しくCheckClickEventスクリプトを作成し取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class CheckClickEvent : MonoBehaviour, IPointerDownHandler { // 主人公キャラクターのダメージ処理スクリプト [SerializeField] private LifeGaugeCharacter lifeGaugeCharacter; public void OnPointerDown(PointerEventData eventData) { Debug.Log("ダメージ"); lifeGaugeCharacter.Damage(1); } } |
IPointerDownHandlerインタフェースを継承し、OnPointerDownメソッドを実装してマウスダウンイベントを受け取るようにします。
ここら辺は

を参照してください。
インスペクタのCheckClickEventでこの後作成する主人公キャラクターのダメージ処理スクリプト(兼操作スクリプト)を設定します。
Ethan(のコライダ)がマウスで押されたらLifeGaugeCharacterスクリプトのDamageメソッドにダメージ数を引数にして渡します。
今回は一律1ダメージにしています。
主人公のダメージ処理スクリプトの作成
今回の主人公はマウスボタンで押された時のダメージ処理をするだけでその他の処理は省きます。
Ethanに新しくLifeGaugeCharacterスクリプトを取り付けます。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class LifeGaugeCharacter : MonoBehaviour { // HP [SerializeField] private int hp; // LifeGaugeスクリプト [SerializeField] private LifeGauge lifeGauge; // Start is called before the first frame update void Start() { // 体力の初期化 hp = 10; // 体力ゲージに反映 lifeGauge.SetLifeGauge(hp); } // Update is called once per frame void Update() { // キャラクター操作処理 } // ダメージ処理メソッド(全削除&HP分作成) public void Damage(int damage) { hp -= damage; // 0より下の数値にならないようにする hp = Mathf.Max(0, hp); if (hp >= 0) { lifeGauge.SetLifeGauge(hp); } } // ダメージ処理メソッド(ダメージ数分だけアイコンを削除) public void Damage2(int damage) { hp -= damage; if(hp < 0) { // ダメージ調整 damage = Mathf.Abs(hp + damage); hp = 0; } if(damage > 0) { lifeGauge.SetLifeGauge2(damage); } } } |
フィールドのhpはSerializeFieldアトリビュートを取り付けていますが、これは単にインスペクタでHPを確認出来るように付けているだけです。
Startメソッドでとりあえず主人公のHPを決定し、LifeGaugeスクリプトのSetLifeGaugeメソッドにHPを渡してライフゲージアイコンをHP分作成しています。
LifeGaugeスクリプトはインスペクタで設定出来るようにし、Canvas子要素のPanelに設定したLifeGaugeスクリプトをドラッグ&ドロップし設定します。
LifeGaugeスクリプトでSetLifeGaugeとSetLifeGauge2メソッドと二つのやり方を書きましたが、それに対応する為にダメージ処理関数も二つ作成しました(それぞれ対応するどちらかのメソッドだけ書いてください)。
DamageメソッドはSetLifeGaugeメソッドを使う時のメソッドで受けたダメージを引数に取ります。
hpからdamageを引いてその後Mathf.Maxで引数で与えた中の最大値をhpに入れなおします。
これはhpが0より下になった時の為の処理で、0より下の数値である時は0をhpに入れます。
hpが0より上(0の時もアイコンを消すために実行)の時にLifeGaugeスクリプトのSetLifeGaugeメソッドにhpを引数にして呼び出します。
Damage2メソッドはSetLifeGauge2メソッドに対応し、引数としてダメージ数を受け取ります。
こちらもhpからdamageを引き、hpが0より下の場合はhpとdamageを足してMathf.Absで絶対値にしdamageに入れなおしています。
これは残りhpよりも大きいダメージを受けた時にhpが0になるまでに受けたダメージを計算する為の処理です。
SetLifeGauge2メソッドでは実際に減らすライフゲージアイコンの数を引数として渡す必要がある為このような処理を行っています。
これでアイコンを使ったライフゲージ機能が出来ました。
ライフゲージを減らしていく方法
アイコン単位ではなく、元からあるライフゲージを減らしていく方法を作成していきます。
この機能を作成すると、
上のようになります。
こちらの場合は

で作成したライフゲージ機能とUIのマスクを使って少し見た目を変えてみただけという感じになります。
まずはライフゲージのアイコンは
上を使います。
わたくしが作った物なのでご自由にお使いください。
上の画像では黒の部分に体力ゲージを表示し、その他の白い部分は透明にします。
この画像をマスクにしハートの部分だけが繰りぬかれて下の画像が見える感じになります。
今回の場合ハートの数は5個だけです。
UIマスクに関しては

を参照してください。
Unityに画像を取り込んだら設定を変更します。
Alpha is Transparencyにチェックを入れアルファを透明にします。
AdvancedのNon Power of 2をNoneにします(画像が壊れる為)。
Wrap ModeをClampにし画像が繰り返されないように制限します。
ライフゲージ表示領域の作成
ライフゲージ表示領域を作成していきます。
ライフゲージアイコンとは別機能なのでCanvasやPanelを再度作ります。
ヒエラルキー上で右クリックからUI→Panelを選択し、以下のように縦の領域をCanvasの15%になるようにします。
Panelを選択した状態で右クリックからUI→Raw Imageを選択します。
Raw ImageのインスペクタのAdd ComponentからUI→Maskを選択し取り付けます。
上のようにライフゲージの表示位置とサイズを設定しRaw ImageのTextureに先ほど取り込んだハートが5つ並んでいるテクスチャを設定します。
ライフゲージのサイズは元を適当に作っているので中途半端な数字になっています・・・・。
これでこのハート5個の画像がマスクになりこの画像を設定したRaw Imageの子要素の画像等はこのハートの部分だけに表示されるようになります。
Raw Imageを選択した状態で右クリックからUI→Sliderを選択します。
Sliderの子要素のBackground、Handle Slide Areaとその子要素はいらないので削除します。
現在の所
上のような階層になります。
Sliderを選択し設定を変えます。
Sliderのサイズは親であるRaw Imageと合わせ、スライダーの値は最大で100、最初から値を100としておきます。
ここら辺はHPと連動させるので、主人公キャラクターの最大値をMax Value、現在のHPをValueに設定する必要があります。
今回はサンプルなので主人公は最初はHPを100持っているとしておきます。
Sliderの子要素のFill Areaもstretch stretchにし親のSliderのサイズに合わせて大きさが変わるようにします。
次にSliderの子要素のFillのSource Imageを選択してDelキーを押して削除します。
こうすることで四隅が丸くなって表示されるのを避けます。
またColorを赤色にし、メーターが満たされている部分は赤色になるようにします。
これで機能が出来たのでEthanを押した時にSliderのValueを操作してHPを減らしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class CheckClickEvent : MonoBehaviour, IPointerDownHandler { [SerializeField] private Slider hpSlider; public void OnPointerDown(PointerEventData eventData) { Debug.Log("ダメージ"); hpSlider.value -= 1; } } |
本来であればLifeGaugeCharacterスクリプトのダメージ処理メソッドを呼び出し、そこからスライダーを操作する必要があります。
ですが今回は確認の為、Ethanを押したらすぐさまSliderの値を変更するようにします(アイコンの時と同じように作ってみてください)。
CheckClickEventのインスペクタでhpSliderにSliderゲームオブジェクトを設定します。
Ethanにダメージを与えるとダメージ数は1なのでスライダーのValueは1ずつ減りますが、Valueを元々100としている為ハート一つ分が20ダメージ数分になります。
ただハートとハートの間はマスクで隠されますのでその部分の違いはわからなくなります。
これで機能が出来上がりました。
終わりに
これでアイコンを使ったライフゲージ機能が出来ましたが、以前どこかの記事で作成したような気がするんですが・・・(^_^;)
まぁ良しとしましょう。
今回の場合はライフゲージでしたが、弾をアイコンで表示させて弾の保持数を表示させるというのにも使えると思います。