HPのメーターを作る

プレイヤーの操作とプレイヤーに追従するカメラの処理を書いた前回の記事に処理を追加して、HPを表示するメーターを作成します。メーターの仕様は敵にぶつかりダメージ判定があると減少し、残りHPの量によって色も変化するというものです。

# 前回の記事
https://qiita.com/yanagiiiiiii_t/items/dd4a21031295d7b88c08

# UIを用いたHPメーターの作成
HPを可視化する棒を作っていきます。Hierarchyビューで右クリックしてUI→Sliderを選択します。作成出来たら、今回はSliderの子オブジェクトのHandle Slide Areaは不要なので削除します。
SliderオブジェクトのInspectorビューを以下の図のように設定します。
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644510/4bc81537-027d-6836-77d9-6c9eff2f8a04.png)
また、SliderオブジェクトのSliderコンポーネントのDirectionをRight To Leftに設定します。
次にSliderの子オブジェクトのBackgroundを以下の図のように設定します。
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644510/1127ca08-57c6-ba70-cb26-22abd52199ae.png)

SliderオブジェクトのFill Areaを以下の図のように設定します。
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644510/e2b31cf1-f143-64cc-f492-e2e75847bedb.png)

Fill Areaの子オブジェクトのFillを以下の図のように設定します。
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644510/68f3c9ed-6892-b865-11b7-2d4599f24fa7.png)

メーターのオブジェクトが出来るのでCanvasの左下に配置します。

# スクリプトからHPを制御する
プレイヤーオブジェクトにアタッチされているPlayerController.csを修正して以下のスクリプトを作成します。

```C#:PlayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //UIを使用する場合は必須

[RequireComponent(typeof(CharacterController))]
public class PlayerController : MonoBehaviour
{
    public float moveSpeed; //普段の移動速度
    public float dashSpeed; //ダッシュ時の移動速度
    public float jumpPower; //ジャンプ力
    private CharacterController controller;
    private Vector3 moveVelocity;
    private Slider hp;
    private Image background, fill;
    private bool isDamage = false; //ダメージ判定

    void Start()
    {
        controller = GetComponent<CharacterController>(); //CharacterControllerを取得
        hp = GameObject.Find("Slider").GetComponent<Slider>(); //SliderオブジェクトのSliderコンポーネントを取得
        hp.value = 0; //HPの初期値を満タンにする
        background = GameObject.Find("Background").GetComponent<Image>(); //BackgroundオブジェクトのImageコンポーネントを取得
        background.color = Color.green; //Backgroundの色を緑にする
        fill = GameObject.Find("Fill").GetComponent<Image>(); //FillオブジェクトのImageコンポーネントを取得
        fill.color = Color.black; //Fillの色を黒にする
    }

    void Update()
    {
        if (Input.GetKey(KeyCode.Z)) //Zキーが押されている場合
        {
            moveVelocity.x = Input.GetAxis("Horizontal") * dashSpeed; //横軸の入力を取得
            moveVelocity.z = Input.GetAxis("Vertical") * dashSpeed; //縦軸の入力を取得
        }
        else
        {
            moveVelocity.x = Input.GetAxis("Horizontal") * moveSpeed; //横軸の入力を取得
            moveVelocity.z = Input.GetAxis("Vertical") * moveSpeed; //縦軸の入力を取得
        }

        transform.LookAt(this.transform.position + new Vector3(moveVelocity.x, 0, moveVelocity.z)); //移動方向を向かせる

        if (controller.isGrounded) //地面にいる場合
        {
            if (Input.GetKeyDown(KeyCode.Space)) //スペースキー入力すると
            {
                moveVelocity.y = jumpPower; //Y軸正の方向に移動
            }
        }
        else
        {
            moveVelocity.y += Physics.gravity.y * Time.deltaTime; //重力によるY軸負の方向への移動
        }

        controller.Move(moveVelocity * Time.deltaTime); //オブジェクトを動かす
    }

    void OnControllerColliderHit(ControllerColliderHit collider)
    {
        if (collider.gameObject.tag == "Enemy" && !isDamage) //ダメージを受けていない時に敵に接触した場合
        {
            StartCoroutine(Damage()); //ダメージ処理

            if (hp.value < 0.8 && hp.value >= 0.5)
            {
                background.color = Color.yellow; //HPが半分から2割の間に減ったらメーターの色を黄色くする
            }

            if (hp.value >= 0.8)
            {
                background.color = Color.red; //HPが2割以下になったらメーター色を赤くする
            }
        }

        if (collider.gameObject.tag == "Food")
        {
            hp.value = 0; //回復アイテムに触れたら体力を満タンにする
            background.color = Color.green; //メーターの色を緑にする
        }
    }

    IEnumerator Damage()
    {
        hp.value += 0.1f; //最大HPの10%のダメージを受ける
        isDamage = true; //ダメージ判定をtrueにする
        yield return new WaitForSeconds(2); //2秒待機
        isDamage = false; //ダメージ判定をfalseにする
    }
}
```

CharacterControllerを使用する場合は衝突判定にOnCollisionEnterではなく、OnControllerColliderHitを使用します。Damage関数の中で2秒待機してからダメージ判定をfalseに戻すようにしているのは、連続でダメージを受けて一瞬でHPがなくなることを防止するためです。今回はvalueの値が0の時、HP満タンとなり、valueが1の時、HPが0となっていますが、Sliderの設定によって変わると思うので、詳しくは参考のURLを参照してください。
最後に3D Objectから適当にオブジェクトを2個作成して、タグをそれぞれEnemyとFoodに設定して動かしてみます。Enemyに当たればHPが減少し、Foodに当たればHPが回復します。またHPの減少に合わせて、メーターの色も変化することがわかります。
![image5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644510/1dcaebb6-eb78-c51f-b844-5295d0bcd9f1.png)

# 参考
https://unity-shoshinsha.biz/archives/1194
https://cbagames.jp/2022/09/06/hpbar/
https://xn--sckyeodz49lj8c.com/%E3%80%90unity%E3%80%91slider%E3%81%A7hp%E3%83%90%E3%83%BC%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9%E3%82%92%E7%9F%A5%E3%82%8D%E3%81%86%EF%BC%81/