はじめに
この記事はHamster Output Advent Calendar 2024の16日目の記事です!
Arbor3とAnimationEventの組み合わせを使ってプレイヤーのダメージ処理やステート遷移を作りたかったのですが...組み合わせの相性が悪い?のかAnimationEventが呼び出されないなどの問題が出てきました。
なので、Animationがどれだけ再生されたのかなどの長さを調べる処理が欲しいなと思い作りました。
実装したソースコード
public static class AnimatorHelper
{
/// <summary>
/// 現在の再生中のクリップの長さを0~1の値で取得する
/// </summary>
public static float GetCurrentClipLength(Animator animator, string stateName)
{
// Animatorを更新する
animator.Update(0.0f);
// 遷移中は0の値を返す
if (animator.IsInTransition(0))
{
return 0.0f;
}
// 現在の再生中のクリップの情報を取得する
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
// ステートのハッシュ値を取得する
var currentStateHash = stateInfo.shortNameHash;
var argumentStateHash = Animator.StringToHash(stateName);
// 現在のステートのハッシュと引き数のステートのハッシュが異なる場合は0を返す
if (currentStateHash != argumentStateHash)
{
return 0.0f;
}
// 現在の再生中のクリップの長さを0~1の値で取得する。
var result = Mathf.Repeat(stateInfo.normalizedTime, 1.0f);
// 現在のAnimationがループしていない場合は1を返す
if (result <= 0.99f && !stateInfo.loop)
{
return 1.0f;
}
return result;
}
}
使い方
static変数なのでどこからでも呼び出せます。
// 長さを保持する変数
var length = AnimatorHelper.GetCurrentClipLength(_animator, "Idle");
// 現在のアニメーションの再生値が特定の値になったらログを出す
if (length >= 0.9f)
{
Debug.Log("Idle");
}
値を0~1の値にする
今回初めて使った処理が、Mathf.Repeatというメソッドで指定した引き数の数値と0を無限にループしてくれる処理です。
// 現在の再生中のクリップの長さを0~1の値で取得する。
var result = Mathf.Repeat(stateInfo.normalizedTime, 1.0f);
最初は、Mathf.Clamp01とかを利用していましたが、Animationがループしている物とかだと、値が1~以上を超えるという問題があり値をループさせる方法はないかと模索した時にRepeatメソッドを見つけました。
もしかしたらこの部分は要らないかも
animatorのCurrentStateInfoの更新が遅れる対策としてanimator.Updateという処理や、Animationが遷移中の時に前の値を返さないようにIsInTransitionなどを利用しています。
その下の方で、さらにステート名が違った場合に処理を中断する部分を入れていますが...もしかしたら要らないかも...?
// ステートのハッシュ値を取得する
var currentStateHash = stateInfo.shortNameHash;
var argumentStateHash = Animator.StringToHash(stateName);
// 現在のステートのハッシュと引き数のステートのハッシュが異なる場合は0を返す
if (currentStateHash != argumentStateHash)
{
return 0.0f;
}
まとめ
Animationの長さを0~1の長さで取得出来るようになったので、0.7のタイミングで何かのイベント発火!という物が作りやすくなりました。正直間違ってたり、遠回りしている可能性もあると思うので詳しい人がいればコメントで教えてください...
AnimationEventも昔から使ってはいるけど、Animation中にメソッドを行う方法で使いやすい物はないのかな...?