ゴマちゃんフロンティア

アザラシが大好きなエンジニアの開発日記です

【Unity】体力ゲージの実装方法の紹介 (一瞬で減る緑ゲージ+徐々に減る赤ゲージ)

time 2016/05/08

今回はUnityで所謂「体力ゲージ」を実装するお話です。

本記事では世の中のゲームでよく見かける、「緑ゲージ減る→赤ゲージが徐々に減る」のやり方をご紹介します。
紹介するプロジェクトの都合でUnityは2019.2を使用していますが、2019.3以降でも特に変わりはないはずです。

テクスチャの準備

まずは体力ゲージのテクスチャを用意します。
今回の例では「緑ゲージ」「赤ゲージ」「ゲージ枠」の3つを作成しました。

Unityへインポートしたら、インポート設定の「Texutre Type」をSpriteに変更します。

Canvas下に体力ゲージを作成

メニューから「GameObject→UI→Image」を選択し、Canvas下にImageを3つ配置します。それぞれ分かりやすい名前に変えておきましょう。

1つ空オブジェクトを挟んだほうが管理しやすいので、ここでは「PlayerGauge」というオブジェクトを作成し、その子に配置しています。
オブジェクトは下から「枠→緑ゲージ→赤ゲージ」の順に並べておきます。これはヒエラルキー上で下にあるオブジェクトほど手前に表示されるためです。

それぞれのオブジェクトの「Soruce Image」にゲージ2色と枠を設定します。
加えて「Image Type」をFilled、「Fill Method」をHorizontal、「Fill Origin」をLeftに設定します。

配置位置やアンカー、サイズはゲームに合わせて調整してください。

体力ゲージ増減用のスクリプト作成

先ほど作成した「PlayerGauge」オブジェクトに以下のスクリプトを設定します。

using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;

public class PlayerGauge : MonoBehaviour
{
    [SerializeField]
    private Image GreenGauge;
    [SerializeField]
    private Image RedGauge;

    private Player player;
    private Tween redGaugeTween;

    public void GaugeReduction(float reducationValue, float time = 1f)
    {
        var valueFrom = player.life / player.maxLife;
        var valueTo = (player.life - reducationValue) / player.maxLife;

        // 緑ゲージ減少
        GreenGauge.fillAmount = valueTo;

        if (redGaugeTween != null) {
            redGaugeTween.Kill();
        }

        // 赤ゲージ減少
        redGaugeTween = DOTween.To(
            () => valueFrom,
            x => {
                RedGauge.fillAmount = x;
            },
            valueTo,
            time
        );
    }

    public void SetPlayer(Player player)
    {
        this.player = player;
    }
}

この例ではPlayerクラスからの利用を想定し、lifemaxLifeというフィールドを持たせ、それをゲージのfillAmount設定に使用しています。
Player以外で使用する場合はそのクラスを指定するなり、体力の現在値・最大値を取得できるインタフェースを定義なりで対応してみてください。

ポイントはGaugeReduction()メソッド内のDOTween.To()です。
緑ゲージのfillAmountは「体力の現在地/最大値」の割合をそのまま代入すればOKですが、赤ゲージは徐々に減らしたいので、DOTween.To()で一定時間継続して設定しています。

スクリプト設定後はインスペクターからImageの参照を設定するのを忘れずに。

他のクラスからの利用方法

あとは他のクラスから参照を取得してGaugeReduction()を呼び出すだけです。
Playerクラスの場合は以下のような感じ。

using UnityEngine;

public class Player : MonoBehaviour
{
    public float life;
    public float maxLife;

    protected PlayerGauge playerGage;

    private void Start()
    {
        playerGauge = GameObject.FindObjectOfType<PlayerGauge>();
        playerGauge.SetPlayer(this);
    }

    public void Damage(float power)
    {
        playerGauge.GaugeReduction(power);
        life -= power;
    }
}

私のゲームではプレイヤーを動的に生成する関係で、PlayerGaugeの参照取得にFindObjectOfType()を使用しています。ただしFind系メソッドは重いらしいので、気になる方は他の方法でどうぞ。
Damage()の呼び出し元についてはゲームによるので割愛します。ダメージを受けたタイミングで呼び出しましょう。

実際の動き

実際のゲーム上で動かすと、以下のような挙動になります。

緑ゲージは一瞬で減って、赤ゲージは徐々に減っていますね。

ちなみにこのゲーム、unityroomさんのサイトで公開中ですので、WebGL上で見たい方はプレイしてみてください。
https://unityroom.com/games/kuritori_usapyon

コメント

  • 現在作っているゲームで使えそうだなと思ったので使わせていただきます
    1つ質問ですが、こちらのコードを使わせていただいたところ
    下のようなエラーが出ました
    The type or namespace name ‘Player’ could not be found (are you missing a using directive or an assembly reference?)

    これはいったいどういう意味なのか、もしおわかりでしたらご回答よろしくお願いします。

    名無し  2023年7月7日 6:16 PM

    • 紛らわしくてすみませんが、Playerは私のゲームのプレイヤーキャラ用のコンポーネントになります。
      なのでコードをそのままコピペしてもPlayerクラスがないと動かないかと思います。
      (記載いただいたエラーはPlayerが未定義の場合に発生します)
      Playerとlife、maxLifeの部分をご自身のゲームに合わせて書き換えて使用いただければ幸いです。

      あかざらし  2023年7月8日 8:28 AM

down

コメントする