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