Unityでダメージを受けてHP表示バーを減らす時にダメージ量をわかりやすくする

記事内に広告が含まれています。

今回はアクションゲームやRPGゲーム等でキャラクターがダメージを受けた時に、キャラクターのHPを表しているバーで受けたダメージ量をわかりやすく表示する機能を作ってみたいと思います。

受けたダメージ分のHPを一気に減らしたり、徐々に減らすというだけでもいい感じなんですが、受けたダメージ量がどの程度なのか?がわかるというのも「この敵の攻撃はこんなにダメージがでかいのか!」と見た目でわかるというのもいい感じです。

HPを徐々に減らしていく方法は既に以下の記事で作っていて、今回の記事でもスクリプト等は大体同じですが、以下の記事だとHPを数値で表していて数値の変化が段々緩やかになるようにしていました。

Unityで敵にダメージを与えた時に少しづつHPを減らす機能を作成
Unityのアクションゲームで敵にダメージを与えた時に敵のHPをカウントダウンしながら減らしていく機能を作成します。

今回はHPをバーで表示し、段々緩やかに減っていく方法だと変な感じになるので一定量ずつ減っていくように変化させます。

今回の機能を作成すると以下のような感じになります。

スポンサーリンク

キャラクターの配置と設定

まずは攻撃対象であるキャラクターを配置します。

今回はスタンダードアセットのEthanを配置することにします(キャラクターは何でも構いません)。

配置したらインスペクタのAdd ComponentからPhysics→CharacterControllerを選択肢取り付けてコライダのサイズを調整します。

Ethanをカメラに近づけるように移動させます。

また攻撃を受けた時の判定に利用するため、Layerに新しくPlayerレイヤーを作成し、設定します(Ethan本体のみで子はDefaultのまま)。

ここまでで以下のようなインスペクタになりました。

攻撃対象のキャラクターのインスペクタ

キャラクターのHP表示バーの作成

次にこのキャラクターのHP表示バーを作成します。

徐々に減らすHPバーの作成

Ethanを選択した状態で右クリックからUI→Sliderを選択し、名前をHPSliderとします。

ヒエラルキーのHPSliderの子のHandle Slide Areaは使わないので選択してDeleteキーを押して削除します。

次にヒエラルキーのCanvasを選択し、CanvasコンポーネントのRender ModeをWorld Spaceに変更します。

これはこのCanvasを他のゲームオブジェクトと同じように3D上を移動出来るようにする為です。

変更したらRect Transformの数値を変更し、キャラクターの頭上に表示されるようにします。

攻撃対象のキャラクター用のHPバーのインスペクタ

次にヒエラルキーのHPSliderを選択し、インスペクタのRectTransformのAnchorと位置を調整します。

Anchor PresetsでShiftキーとAltキーを押しながらstretch stretchを選択します。

先ほどヒエラルキーのHandle Slide Areaを削除したのでSliderコンポーネントのTarget GraphicがMissingになっているので選択してDeleteキーを押しNoneにしておきます。

HPSliderと同様に子のBackgroundとFill AreaのAnchorもstretch stretchに変更しておきます。

これはCanvasのサイズに合わせて背景とバーのサイズを合わせる為に行います。

BackgroundとFill AreaのRectTransformのAnchorを変更

次にFill Areaの子のFillを選択し、インスペクタのWidthを0にします。

FillのRectTransformのWidthを0にする

また、Fillはダメージを受けた時に徐々にHPを減らすバーとして使うのでFillのインスペクタのImageコンポーネントのColorで色を変更します。

徐々に減らすHPバーの色を変える

ここまで作ったらヒエラルキーのHPSliderを選択し、インスペクタのSliderのValueの値を変更し以下のようになるかを確認します。

HPバーのSliderのValueを変更し、確認した結果

これで徐々に減らすHPバーの作成が出来ました。

一括で減らすHPバーの作成

次にダメージを受けた時に一括でダメージ分のHPを減らすバーを作成します。

ヒエラルキーのHPSliderを選択し、Ctrl+Dキーを押して複製し、名前をBulkHPSliderとします。

BulkHPSliderの子のBackgroundを選択し、Deleteキーを押して削除します。

ヒエラルキーのBulkHPSliderの子のFillを選択し、ImageコンポーネントのColorを青色に変更しておきます。

これで一括で減らすHPバーの作成が出来ました。

キャラクターとHPバーの階層は以下のようになります。

攻撃対象のキャラクターとHPバーの階層

スクリプトの作成

攻撃対象のキャラクターとそのキャラクターが持つHPのバーの作成が出来たので、次はHPのバーをカメラの方に向けるスクリプト、ダメージを受けた時にHPバーの変更を行うスクリプトやマウスクリックした時にキャラクターをクリックしたかどうかを判定するスクリプトを作成していきます。

HPバーをカメラの方向に向けるスクリプト

HPバーを常にカメラの方向に向けるRotateDamageUIスクリプトを作成し、Canvasゲームオブジェクトに取り付けます。

キャラクターが回転した時にHPバーが一瞬乱れる場合はUpdateメソッドをLateUpdateメソッドに変更してください。

HPバーを変更するスクリプト

敵のHPを管理するEnemyHPManagerスクリプトを作成し、キャラクター(Ethan)のゲームオブジェクトに取り付けます。

maxHPはキャラクターの最大HP

hpは現時点でのhp

finalHPはダメージを受けた後の最終的なhp

countTimeは前回HPバーを減らしてからの経過時間

nextCountTimeは次にHPバーを減らすまでの間隔時間

hpSliderはHPSliderゲームオブジェクトのSliderコンポーネントを入れます。

damageは現在のダメージ量

amountOfDamageAtOneTimeは1回に減らすダメージ量

isReducingは現在HPをへらしているかどうか

delayTimeはダメージを受けてから実際にHPバーを減らしていくまでの待機時間

となっています。

Startメソッドではキャラクターゲームオブジェクトの階層を辿ってHPSliderとBulkHPSliderのSliderコンポーネントを取得しフィールドに保持しています。

その他はHPとHPバー用のSliderの初期設定です。

UpdateメソッドではisReducingがfalseの時はreturnを使ってそれ以降の処理をしません。

countTimeがnextCountTime以上になったらMathf.Minを使ってamountOfDamageAtOneTimeとdamageの小さい方をtempDamageに入れています。

これは1回で減らすダメージ量を計算したいんですが、残りのダメージ(damage)の方が小さいと実際に受けたダメージよりも多いamountOfDamageAtOneTimeの値を1回のダメージとして与えてしまう為です。

なので小さい方の値を1回のダメージとして計算する為にMathf.Minで小さい方の値を取得します。

1回のダメージ量を計算したらhpからそのダメージ量を減らし、maxHPで割って現在のHPの最大HPに対する割合を計算します。

Sliderの値の範囲はデフォルト値では0~1の間になっているので(変更していない為)最大HPに対する現在のhpの割合を計算し、0~1の値にしています。

(float)でhpの値をfloat型にキャストしていますが、これはhpとmaxHPはint型で割った時に小数点の値を取得出来ない為で、一旦hpをfloat型にすることで計算結果にfloat値を得られるようにしています。

その後、1回に与えたダメージ量分のダメージをdamageから減らします。

次にMathf.Max(大きい方の値を取得)を使ってdamageと0の大きい方をdamageに入れなおしています。

これはダメージ量がマイナスになるのを防ぐ為で、damageは最低でも0になるようにしています。

ダメージ量が0以下の場合は与えるダメージがもうないのでisReducingをfalseにします。

countTimeにTime.deltaTimeを足して経過時間を計算します。

TakeDamageメソッドはキャラクターが攻撃を受けた時に呼び出すメソッドです。

finalHPからdamageを減らしてfinalHPに入れます。

またそのfinalHPと0の大きい方をtempHPに入れます。

tempHPをmaxHPで割ったものをbulkHPSliderの値に入れます。

こちらは一括でダメージ分を減らす為にTakeDamageメソッド内で値を変更しています。

フィールドのdamageに今受けたダメージ分を足して合計ダメージ量を増やします。

Invokeメソッドを使ってdelayTime時間後にStartReduceHPメソッドを実行するようにします。

こうすることでダメージを受けてからdelayTime経った後にHPバーを徐々に減らす処理を実行することになります。

StartReduceHPメソッドではisReducingをtrueにしているだけです。

キャラクターを攻撃するスクリプトの作成

最後にキャラクターをマウスで押した時にダメージを与えるClickAttackScriptスクリプトを作成し、MainCamera(他のゲームオブジェクトでもOK)に取り付けます。

mainCameraにはメインカメラを入れます。

attackPowerは攻撃力を設定します。

Startメソッドでメインカメラを取得しmainCameraに保持して置きます。

Updateメソッドではマウスの左ボタンを押した時にメインカメラからマウスを押した場所にレイを飛ばしその情報をrayに保持しています。

そのrayの情報を使ってメインカメラからマウスを押した場所の方向に1000m先までレイを飛ばし、Playerレイヤーを持つゲームオブジェクトと接触したらその情報をhitに入れます。

その相手からEnemyHPManagerコンポーネントを取得し、TakeDamageメソッドにattackPowerを渡して実行します。

これで機能が完成しました。

終わりに

どれだけのダメージを受けたのか視覚的に確認出来ると便利ですね。

今PS4のニーアレプリカントをプレイしているんですが、ちょうど今回のような機能があったので作ってみました。

タイトルとURLをコピーしました