2020/11/09
今回は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クラスからの利用を想定し、lifeとmaxLifeというフィールドを持たせ、それをゲージの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