1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Hamster OutputAdvent Calendar 2024

Day 16

【Unity】Animatorの現在再生中のAnimationの長さを取得する

Posted at

はじめに

この記事は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中にメソッドを行う方法で使いやすい物はないのかな...?

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?