Last Updated 2024.12.06
↑赤い部分のことです
「遅れて減る体力ゲージ」に関しては、検索すれば色んな所でやり方は出てくるのですが、ここではUnityの基本的な機能のみで実装した例になります。
実際に作ってみたサンプル
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;// 必須
using static PlayerState;// 必要
// 徐々に減る体力ゲージのスクリプト
public class DelayLife: MonoBehaviour
{
private GameManager gameManager;
private Image _2PDelayLife;
[SerializeField]
private float delaySpeed = 0.04f;// 減る速度
private float delayberLife = 0;// 赤ゲージの頂点位置(ダメージを受けた際の体力)
private float nowLife;// 現在の体力(赤ゲージの目標位置)
public bool _isDelay;// 徐々に減るゲージのスイッチ
public int countup;// 計測用のタイマー
private bool _isReduce;// 減少開始するフラグ
[SerializeField]
private PlayerState playerState;// プレイヤーの状態を管理してるスクリプト
void Start()
{
gameManager = transform.parent.gameObject.GetComponent<GameManager>();
_2PDelayLife = transform.Find("2PDelayLife").GetComponent<Image>();
}
void FixedUpdate()
{
if (!_isDelay) return;// スイッチがなければ何もしない
nowLife = gameManager._2PNowLife;
_2PDelayLife.fillAmount = (delayberLife * 0.01f) - 0.01f;
countup++;
// プレイヤーがダメージ状態でなければ
if (countup >= 30 &&
playerState._2PPlayerState != PlayerState.nowPlayerState.Damage)
{
_isReduce = true;// 赤ゲージの減少開始
}
// 50フレームを超えたら自動で減少開始
if (countup >= 50) _isReduce = true;
if (_isReduce)
{
// ディレイする体力を徐々に反映する
delayberLife = Mathf.Floor(Mathf.Lerp(delayberLife, nowLife, delaySpeed));
if (delayberLife == gameManager._2PNowLife)// 現在のライフと赤のライフが一致したら
{
_isDelay = false;
_isReduce = false;
countup = 0;
}
}
}
}【やっていること】
フレーム単位で管理したかったので、計測は時間ではなく専用の《countup》を宣言。
「_isDelay」はダメージ処理を管理する外部スクリプトから使用します。
FixedUpdate()内で「_isDelay」が入ってる状態なら起動。
ダメージを受けた時点の体力を赤ゲージに反映し、フレーム計測開始。
プレイヤーの状態がダメージモーションを抜けたら、赤ゲージを現在の体力値まで減らします。
KO時の特殊やられモーションのような例外もあるので、対策としてフラグが入ってる状態で50フレームが経過した場合にも自動で減るようにしています。
”ダメージモーションでなければ” の条件に "countupが30を超えていたら" というのがありますが、これは、入れていないと条件抜けが発生するケースがあるためです。
具体的には、ダメージモーションに推移するまで数フレかかるアニメーション(ブレンドの時間が長いと発生する)だと「playerState」の状態がまだ「Damage」に移行しておらず、即座に「_isReduce」に入ってしまうため、赤ゲージも即減少を始めてしまいます。
※30という数字は余裕を持たせて設定してるのですが、これは「一番短いダメージモーションの総フレーム数」に合わせて設定するのが正解の気がします。あるいは、ダメージ状態から復帰するタイミング(受け身とか、ダメージモーション→待機状態)、要はリカバリーのタイミングで条件が入るよう設定するかですね。この辺はもう少し詰める予定です。
プレイヤーの状態を管理するスクリプト
※プレイヤーの状態を管理する「playerState」はインスペクター欄で設定してます。
以前扱ったAnimator関係の日記 後半部分で触れていた「Animatorでプレイヤーの状態を判定する」スクリプトのことです。
ダメージを受ける
あとはダメージ処理を管理するスクリプトに
[SerializeField]
private DelayLife delayLife;// 遅れて追従するゲージのスクリプト
を宣言し、ダメージ発生時の処理に
// 徐々に減るゲージのフラグを入れる
delayLife._isDelay = true;
// もし既にディレイ用のカウントアップが始まってるならカウントを初期化
if (delayLife.countup != 0) delayLife.countup = 0;
を追記するだけです。
ダメージを受ける度に「Countup」の値を0にすることで、「Damage」Tagが設定されてるモーション中は『赤ゲージが減らない = 攻撃が繋がってる』という、格ゲーっぽい仕様を再現しています。
動作確認
画像自体は前回と同じです。
これを拡張していけば、格ゲーではお馴染みの『ファーストアタック』とか『nヒットコンボ!』みたいな条件も取れるところまできたのですが、今回はここまでになります。