4.1 一般的なアニメーションのスクリプティング概要

Tutorial

Beginner

+10XP

50 mins

(14)

Unity Technologies

4.1 一般的なアニメーションのスクリプティング概要

本チュートリアルでは、アニメーションスクリプティングの基本に触れます。具体的には、アニメーターコントローラーのデータを取得し、設定する方法を学びます。

このチュートリアルは、C# スクリプトの経験がある学習者を対象とした、一般的なアニメーションのスクリプティングの概要です。アニメーションのスクリプティングのステップバイステップの手順については、このコースの範囲外です。

1. 概要

本チュートリアルでは、アニメーションスクリプティングの基本に触れます。具体的には、アニメーターコントローラーのデータを取得し、設定する方法を学びます。

ここで説明するスクリプティングのほとんどは、Animator コンポーネントにあるメソッドです。これらのメソッドを使用する前に、Animator コンポーネントへの参照を見つけることが前提となります。

このチュートリアルは、C# スクリプトの経験がある学習者を対象とした、一般的なアニメーションスクリプティングの概要です。アニメーションのスクリプティングのステップバイステップのガイドは、このコースの範囲外です。

2. はじめる前に

このチュートリアルでは、「3D アニメーションシステム入門」Unity プロジェクトを使用しています。まだダウンロードされていない方は、続ける前にダウンロードしてください。

プロジェクトのダウンロードが完了したら:

1. プロジェクトを Unity エディターで開きます。

2. Project ウィンドウで、Assets > 4.1 - Introduction to general animation scripting と進みます。

3. アニメーターパラメーター値の制御

アニメーションに影響を与える最も基本的なスクリプティングの手法は、アニメーターパラメーターの値を取得したり設定したりするものでしょう。

アニメーターパラメーターは、アニメーターの動作を制御する際に、以下のような様々なことに使用されます:

  • 遷移を開始するタイミング
  • ブレンドツリーのブレンド値とブレンド位置
  • ステートの各種設定

4. アニメーターパラメーター値の設定

アニメーターパラメーターの値をランタイムで制御できることは非常に重要です。これには 4つのメソッドがあります:

  • animator.SetBool()
  • animator.SetFloat()
  • animator.SetInteger()
  • animator.SetTrigger()


これらのメソッドが機能するためには、それぞれのメソッドが 2つのことを知っている必要があります:

  • どのパラメーターを設定しているか
  • どのような値に設定するのか


例外はトリガーパラメーターです。これらは値を持たず、設定するパラメーターのみを知る必要があります。


どのパラメーターが設定されているかをメソッドに知らせるには、2つの方法があります:

  1. 名前の文字列を使用する
  2. ハッシュと呼ばれる名前を整数で表現したものを使う

つまり、例えば、float パラメーターの値を設定する呼び出しは、以下のようになります:

animator.SetFloat(“Speed”, 5f);


あるいは、こんな風に:

animator.SetFloat(speedParameterHash, 5f);

ハッシュ文字列

2つ目のケースでは、speedParameterHash は、使用する前に見つける必要のあるスピードパラメーター名のハッシュです。可能な限り、文字列ではなく名前のハッシュを使用することをお勧めします。

アニメーターコントローラーの任意の文字列に対してハッシュを生成するには、以下のスタティックメソッドを使用します:

Animator.StringToHash()

このメソッドは、変換したい名前を 1つの文字列パラメーターとして受け取ります。

このメソッドは、Static (静的) でコンパイル時の定数です。つまり、以下のようにメンバー変数を初期化するために使用することができます:

int speedParameterHash = Animator.StringToHash(“Speed”);

このハッシュは必須ではありませんが、パラメーターはメソッドのすべてのインスタンスで同じ名前になる可能性が高いため、static (静的) に設定されています。

ハッシュは常に同じであるため、誤って変更されないようにリードオンリーにすることができます。これらの調整により、以下のようなコードになります:

static readonly int speedParameterHash = Animator.StringToHash(“Speed”);

サンプルを見てみよう

完全なサンプルスクリプティングの例を見るには:

1. Project ウィンドウで、Assets > 4.1 - Introduction to general animation scripting と進みます。

2. SetParametersExample アセットをダブルクリックして、コードエディターでメソッドを開きます。

using UnityEngine;
public class SetParametersExample : MonoBehaviour
{
   public Animator animator;
   static readonly int speedParameterHash = Animator.StringToHash("Speed");
   void Update()
   {
       animator.SetFloat(speedParameterHash, 5f);
   }
}

5. アニメーターパラメーター値の取得

パラメーターの話に戻りますが、パラメーターを設定する方法はすでに習得済みです。しかし、パラメーターの値を取得することが有効な場合もあります。そのためには、以下のような方法があります:

  • animator.GetBool()
  • animator.GetFloat()
  • animator.GetInteger()


トリガーパラメーターは値を持たないため、その値を取得するメソッドはありません。

これらのメソッドは、値を設定するものと非常によく似た方法で動作します。違いは、値を取得するパラメーターの名前という、1ビット分の情報量しか必要としないことです。

サンプル

各メソッドは、そのパラメーターの値を返します。つまり、例えば、bool パラメーターの値を取得する呼び出しは、以下のようになります:

bool isCharacterGrounded = animator.GetBool(“IsGrounded”);


あるいは、こんな風に:

bool isCharacterGrounded = animator.GetBool(isGroundedParameterHash);



アニメーターパラメーターの値を取得する最も一般的な理由の一つは、スクリプトではなく、インポートされたアニメーションによって設定されている場合です。

インポートされたアニメーションには、追加の Animation Curve (アニメーションカーブ) を使用するオプションがあり、これらの追加の Animation Curve にはそれぞれ名前を付ける必要があります。この名前が float アニメーターパラメーターと同じであれば、アニメーションが評価されている間、パラメーターの値は Animation Curve の値に設定されたものになります。

これらの Animation Curves には重み付けがされているので、2つのアニメーションをブレンドする場合、アニメーターパラメーターの値はそれぞれのアニメーションの値をブレンドしたものになります。

6. アニメーターレイヤーのウェイトを制御する

また、アニメーターパラメーターの取得および設定と同様の方法で、アニメーターレイヤーのウェイトを取得し、設定することができます。

以下の方法で行うことができます:

  • animator.SetLayerWeight()
  • animator.GetLayerWeight()

これらのメソッドは、アニメーターパラメーターに相当するものと同様の情報量を必要とします。これらのメソッドは、何を取得または設定しているのか、そしてどのような値にウェイトを設定するのかを知る必要があります。

サンプル

これらの方法を使った最終的なコードは、以下のようになります:

animator.SetLayerWeight (1, 0.5f);


あるいは、こんな風に:

float shootingLayerWeight = animator.GetLayerWeight (2);


これらの操作は、複数のアニメーターレイヤーを使用するアニメーターコントローラーにとって重要です。詳しくは、「Creating and configuring Animator Layers」をご覧ください。

7. 制御フローの概要

アニメーターパラメーターの主な役割の一つは遷移の制御ですが、より個別に再生されるアニメーションの流れを制御したい場合もあるでしょう。これには以下の方法があります:

  • Play()
  • PlayInFixedTime()
  • CrossFade()
  • CrossFadeInFixedTime()

8. Play と PlayInFixedTime の使用

Play() PlayInFixedTime() はどちらも同じこと (指定された名前のステートを再生) をします。ただ、その方法が少し違うだけです。

どちらの方法も、最大 3つのパラメーターを持つことができます:

  • 再生されるステートの名前(文字列またはステートの名前のハッシュ)
  • 再生するステートがあるレイヤーのインデックス
  • ステートが再生を開始する時間は:


両者の違いは、Play() の時間パラメーターが 0~1 の正規化された時間であること、PlayInFixedTime() の時間パラメーターが秒単位であることです。

Play() の場合、最後のパラメータに 0.5f の値を指定すると、ステートの途中で遷移の再生を開始することを意味します。PlayInFixedTime() の場合は、ステートの半秒後に再生を開始します。

サンプル

これらのメソッドの呼び出しは、以下のようになります:

animator.Play(“Run”, 0, 0.1f);


あるいは、こんな風に:

animator.PlayInFixedTime(shootStateHash, 1, 0f);


2つ目のケースでは、shootStateHash は、プレイするステートの名前のハッシュです。

9. CrossFade と CrossFadeInFixedTime の使用

CrossFade() CrossFadeInFixedTime() メソッドは、Play() および PlayInFixedTime() とよく似ていますが、より遷移に近い動作をします。そのため、Play() メソッドや PlayInFixedTime() メソッドよりも多くの情報を必要とします。

CrossFade() メソッドと CrossFadeInFixedTime() メソッドはともに、最大で 5つのパラメーターを持つことができます:

  • クロスフェードの対象となるステートの名前(文字列またはステートの名前のハッシュ)
  • フェードにかかる時間
  • クロスフェードしているステートのレイヤーのインデックス
  • 遷移しているステートでのオフセット
  • 開始するフェード処理時間

Play() や PlayInFixedTime() と同様に、CrossFade() はパラメーターに正規化された時間を使用し、CrossFadeInFixedTime() は秒単位の時間を使用するという違いがあります。

ただし、最後のパラメーター(フェードをどのくらいで開始するか)は、どちらの方法でも正規化された時間でなければならないという例外があります。

10. 制御フローのサンプルを確認する

これらを使ったサンプルを見てみましょう:

animator.CrossFade(walkStateHash, 1f, 0, 0.1f, 0f);


上のサンプルでは、walkStateHash で表される名前のステートにクロスフェードしています。このクロスフェードには、フェード元のステートと同じ長さの時間がかかります。これは、Normalized Transitionduration パラメーター 1 が設定されているためです。


フェードしているステートは、アニメーターレイヤーのインデックスが 0 であることから、ベースアニメーターレイヤー上にあります。クロスフェードが始まると、3 つのことが起こります:

  1. 通常の遷移と同様に、フェードアウトしていくステートの再生が始まります。
  2. タイムオフセット0.1f のパラメーターを使用しているため、遷移先のステートは 10分の1 から再生を開始します。
  3. 正規化された時間0f から始まっているので、アニメーション全体を再生します。

サンプルを見てみよう

Unity エディターでスクリプトのサンプルを確認するには:

1. Project ウィンドウで、Assets > 4.1 - Introduction to general animation scripting と進みます。

2. FlowControlExample アセットをダブルクリックして、Code エディターでメソッドを開きます。

using UnityEngine;
public class FlowControlExample : MonoBehaviour

{
   public Animator animator;
   static readonly int shootStateHash = Animator.StringToHash("Shoot");
   static readonly int walkStateHash = Animator.StringToHash("Walk");
   void Start()
   {
       animator.Play("Run", 0, 0.1f);
   }
   void Update()
   {
       if(Input.GetKeyDown(KeyCode.Space))
           animator.PlayInFixedTime(shootStateHash, 1, 0f);
       if(Input.GetKeyDown(KeyCode.LeftShift))
           animator.CrossFade(walkStateHash, 1f, 0, 0.1f, 0f);
   }
}

11. MonoBehaviour のメッセージ

MonoBehaviour の Update または FixedUpdate コールでは、パラメーターの取得や設定、再生や異なるステートへのクロスフェードなど、ほとんどのアニメーションスクリプティングを行うことができます。ただし、他の場所で行うべきアクションもあります。具体的には、MonoBehaviours の一部である 2つのメッセージメソッド (OnAnimatorMove と OnAnimatorIK) で行います。

OnAnimatorIK

OnAnimatorIK メソッドは、Animator コンポーネントにヒューマノイドのアバターがある場合にのみ呼び出されます。どんな IK にも使用する必要があります。 この方法については、「4.2 Introduction to Humanoid-specific animation scripting」で詳しく説明しています。

OnAnimatorMove

OnAnimatorMove メソッドは、ヒューマノイドアニメーションとジェネリックアニメーションの両方で呼び出されます。通常、Root Motion は Animator コンポーネント上で有効または無効になっています。しかし、MonoBehaviour が OnAnimatorMove メソッドを呼び出すと、Root Motion (軌道) を制御することになります。これは Animator コンポーネントへの変更と見ることができます。


OnAnimatorMove メソッドを空にすると、アニメーターはルートモーションがないかのように動作します。ただし、animator.deltaPosition と animator.deltaRotation プロパティを使用して、これを変更することができます。

これらの変更を OnAnimatorMove メソッドの Root Transform に適用すると、アニメーターコントローラーはルートモーションを正常に適用しているように動作します。アニメーターコントローラーに特有の要件に基づいて、これを変更することができます。

実行順序

これらのメッセージについて重要なことは、アニメーターコントローラーの内部更新プロセスに合わせて呼び出されるということです。これは Animator コンポーネントに設定されている Update Mode に応じて変更されます。


Update Mode Normal に設定されている場合は、Update メソッドが最初に呼ばれ、次にOnAnimatorMove、OnAnimatorIK、LateUpdate の順に呼ばれます。

Update ModeAnimate Physics に設定されている場合、最初に FixedUpdate が呼び出され、次に OnAnimatorMove が呼び出されます。その後、物理演算システムが内部アップデートを実行して衝突をチェックし、解決してから最後に OnAnimatorIK が呼び出されます。

12. ステートとアニメーションクリップの情報

アニメーターコントローラーで現在行われていることについて、パラメーターの値以外の情報を知りたい場合があります。そのために、アニメーターコントローラーの状況を知るための方法がいくつかあります。

遷移中ですか?

アニメーターコントローラーの特定のアニメーターレイヤーがステート間で遷移しているかどうかを調べるには、以下のようにします:

animator.IsInTransition()

これは、チェックしたいアニメーターレイヤーのインデックスを整数のパラメーターで受け取り、アニメーターレイヤーが現在遷移中であれば true を、そうでなければ false を返します。

どのステートが再生しているの?

また、アニメーターコントローラーが現在どのステートにあるのか確認し、アニメーターコントローラーがそのアニメーターレイヤーで遷移している場合、次のステートを確認することもできます。これには、以下の 2つのメソッドを使用して実行できます:

  1. animator.GetCurrentAnimatorStateInfo()
  2. animator.GetNextAnimatorStateInfo()


これらの構造体は、問い合わせたいアニメーターレイヤーのインデックスを整数で受け取り、AnimatorStateInfo という構造体を返します。これには、以下のようなステートに関する簡潔な情報が含まれています:

  • Length(長さ)
  • 名前とタグのハッシュ
  • Speed(速度)


アニメーターレイヤーが遷移していないときに(次のステートがない状態)で、次のステートの情報を得ようとすると、全体的にデフォルト値の AnimatorStateInfo を受け取ることになります。

アニメーションクリップの情報の取得

再生中のアニメーションクリップの情報を知りたい場合は、以下の 2つのメソッドを使用できます:

  1. animator.GetCurrentAnimatorClipInfo()
  2. animator.GetNextAnimatorClipInfo()


これらは、AnimatorStateInfo を取得するためのメソッドと同様に動作します。どちらもアニメーターレイヤーのインデックスパラメーターを持っていますが、代わりに AnimatorClipInfos の配列を返します。

これらは、再生されるアニメーションクリップとそのウェイトへの参照を持つ構造体です。このウェイトはブレンドのウェイトで、ブレンドツリーと遷移の両方が考慮されます。アニメーターレイヤーのウェイトは考慮されません。

13. まとめ

本チュートリアルでは、Unity で汎用的なアニメーションを行うためのスクリプティングについて説明しました。スクリプティングを使って以下のようなことをする方法を学びました:

  • アニメーターパラメーター値の制御と設定
  • アニメーターレイヤーのウェイトを制御
  • Play と PlayInFixedTime の使用
  • CrossFade と CrossFadeInFixedTime の使用
  • フロー制御を見直す
  • Monobehaviour メッセージの制御
  • ステートとアニメーションクリップの情報を探す

次は、ヒューマノイドのアニメーションを扱うときにのみ使われるスクリプティングについて説明します。

Complete this Tutorial