Version: 5.4
アニメーション
旧 GUI

アニメーションのスクリプティング (非推奨)

Unity のアニメーションシステムは、スキンメッシュされたキャラクターの素晴らしいアニメーションを可能にします。アニメーションシステムは、アニメーションのブレンド、ミキシング、加算的アニメーション、歩行周期の同期、アニメーションのレイヤー、さまざまな方法によるアニメーション再生の制御(時間、速度、ブレンドウェイト)、頂点ごとに1、2 または 4 ボーンを割り当てたメッシュスキニングだけでなく、物理ベースのラグドールと、プロシージャルなアニメーションもサポートしています。最良の結果を得る為に、最適なパフォーマンスのためのキャラクターモデリング を参照してください。Unity で最適なパフォーマンスのリグキャラクターを作成するための、最良の方法と技法について説明しています。

快活なキャラクターの作成は、ゲーム空間を 移動 させ、必要に応じて適切な アニメーション をさせる、という、2つの要素から成り立っています。キャラクターの移動に関してもっと知りたい場合は、キャラクターコントローラーに目を通してください。このページでは、アニメーションに焦点をあわせています。事実上、キャラクターのアニメーティングは Unity のスクリプトインターフェースを通して行われます。

快活なキャラクターの事前設定を公開しています。実例デモでダウンロードできます。このページで基礎を学んだ後、アニメーションスクリプトインターフェースを参照することもできます。

アニメーションのブレンディング

こんにちのゲームは、アニメーションのブレンディングが、キャラクターをスムーズにアニメーションすることを保証する、必要不可欠な機能になっています。アニメーターが、例えば、歩く繰り返し、走る繰り返し、アイドリングのアニメーションか射撃のアニメーションとアニメーションを分けて作成します。ゲーム中のどの時点でも、アイドルアニメーションから歩行サイクルまたはその逆へと、望みの移行をすることができます。当然、スムーズにし突然の急な動きは避ける移行を望んでいます。

ここでアニメーションのブレンディングの出番です。Unity 内では、同じキャラクター上のアニメーション再生の番号をいくつも持つ事ができます。すべてのアニメーションは、混ぜたか追加した、ともに最終のアニメーションで生成します。

最初のステップは、アイドルから歩行アニメーションへの、なめらかなキャラクターブレンドを作成できる様にすることです。スクリプトでの作業を楽にするために、まずアニメーションの Wrap ModeLoop に設定します。それから、スクリプトがアニメーションを一つだけ再生するかどうか確認するために Play Automatically をオフにしておきます。

最初のアニメーティングキャラクター向けのスクリプトは、割と単純です。どうやって早くキャラクターが動いているか、見いだすための方法のみ必要です。その後、歩くからアイドルへゆっくりアニメーションします。簡単なテストのために、標準の入力軸を使う事にします。

function Update () {
   if (Input.GetAxis("Vertical") > 0.2)
       animation.CrossFade ("walk");
   else
      animation.CrossFade ("idle");
}

プロジェクトで、このスクリプトを使うには:

  1. Assets > Create > Javascript で Javascript ファイルを作成する。
  2. その中にコードをコピー&ペースト
  3. キャラクターの上にスクリプトをドラッグ(アニメーションを持つ GameObject にアタッチする必要があります)。

プレイボタンを押すと、キャラクターは、上の矢印キーを押し続けで場所内を歩き始め、離すとアイドルポーズに戻ります。

アニメーションのレイヤー

レイヤーは、グループアニメーションと重み付け優先順位を付けることで、非常に有用な概念です。

Unity のアニメーションシステムでは、すきなだけ沢山のアニメーションクリップをブレンドする事ができます。手動でブレンドウェイトを設定する事もできますが、ウェイトを自動的にアニメーションさせる animation.CrossFade() を使うと簡単です。

ブレンドの重みは、適用される前に常に正規化される

例えば、歩行サイクルと走行サイクルがあり、両方とも重みは 1(100%)になっているとします。Unity が最終的なアニメーションを生成するときには重みを正規化するので、歩行サイクルのアニメーションが 50% 、走行サイクルも 50% になります。

ですが大抵の場合、2 つのアニメーションを再生する時には、どちらかのアニメーションを優先したいので、片方により重みをつける事になります。もちろん手動で重みの合計値を 100% にすることも可能ですが、この目的であればレイヤーを使う方が、より簡単です。

レイヤリングの例

例えば、射撃、それにアイドルと歩行サイクルのアニメーションがあるとします。歩行とアイドルのアニメーションは、プレイヤーの速度をベースにブレンドされますが、プレイヤーが射撃するときは、射撃アニメーションだけを再生したくなります。従って、基本的に射撃アニメーションの優先順位が高い、という事になります。

これを実現する簡単な方法は、射撃中にも歩行やアイドルのアニメーションを単純に再生し続けることです。これを行うには、射撃アニメーションが、アイドルと歩行のアニメーションより高いレイヤーに作成されているか確認する必要があります。つまり、射撃アニメーションが最初にブレンドウェイトを受ける事になります。射撃アニメーションがブレンドウェイトを 100% 使っていない場合に限り、歩行とアイドルのアニメーションが分配を受けます。射撃アニメーションにクロスフェードするときは、重みは短時間で 0 から 100% に変化します。最初のうちは、歩行とアイドルのレイヤーにもブレンドウェイトが分配されていますが、完全に射撃アニメーションへ移行すると、まったく配分を受け取りません。これがまさに必要な機能です!

function Start () {
   // すべてのアニメーションがループするように設定します
   animation.wrapMode = WrapMode.Loop;
   // "射撃" は除きます
   animation["shoot"].wrapMode = WrapMode.Once;

   // idle と walk を下層レイヤーに加えます (デフォルトのレイヤーは常に 0)
   // これによって 2 つのことが起こります
   // shoot と idle/walk は違うレイヤーにあるので
   // CrossFade を呼び出すときに互いの再生に影響を与えません。
   // shoot は上層のレイヤーなので、フェードインするときに、その アニメーションは 
   // idle/walk のアニメーションに取って代わります。
   animation["shoot"].layer = 1;

   // すでに再生中のアニメーションを停止します。
   //(ユーザーが play automatically を無効にするのを忘れた場合)
   animation.Stop();
}

function Update () {
   // 押されたキーによって
   // walk アニメーションか idle アニメーションを再生します
   if (Mathf.Abs(Input.GetAxis("Vertical")) > 0.1)
      animation.CrossFade("walk");
   else
      animation.CrossFade("idle");

   // 射撃
   if (Input.GetButtonDown ("Fire1"))
      animation.CrossFade("shoot");
}

デフォルトでは、animation.Play()animation.CrossFade() は、同じレイヤー内にあるアニメーションを停止したり、フェードアウトできます。これこそが、多くの場面で必要な機能です。射撃、アイドル、走行の例において、アイドルと走行の再生は、射撃アニメーションに影響しませんし、その逆も同様です(望むならこの振る舞いは、animation.CrossFade のオプションパラメーターで変更できます)。

アニメーションのミキシング

アニメーションミキシングを使うと、部分的に適用するアニメーションをいくつか用意することで、作成しなければいけないアニメーションの数を削減することができます。つまり、この方法ではアニメーションをさまざまに組み合わせて使う事ができる、という事です。

AnimationState が与えられた AddMixingTransform() を呼び出すことにより、アニメーションへアニメーションミキシング変換を追加する。

ミキシングの例

手を振るアニメーションを例として、ミキシングを考えてみます。キャラクターがアイドリング状態のときと歩行状態のときに、手を振らせたいとしましょう。アニメーションミキシング無しでは、アイドリング状態と歩行状態それぞれ用に、手を振るアニメーションを分けて作成しなくてはなりません。ですが、肩のトランスフォームに手を振るアニメーションをミキシングすれば、肩から手までの部分だけを、手を振るアニメーションで制御する事ができます。その場合、体の残りの部分は、手を振るアニメーションには影響されず、アイドルか歩行アニメーションを再生し続けます。従って、この場合、手を振るアニメーションを一つだけ作成すれば良いことになります。

/// Transform 変数を使ってミキシングトランスフォームを加えます
var shoulder : Transform;
animation["wave_hand"].AddMixingTransform(shoulder);

もう一つの例、パスを使用する

function Start () {
   // 代わりに、パスを使ってミキシングトランスフォームを加えます
   var mixTransform : Transform = transform.Find("root/upper_body/left_shoulder");
   animation["wave_hand"].AddMixingTransform(mixTransform);
}

加算的アニメーション

加算的アニメーションとアニメーションミキシングは、ゲーム作成に必要なアニメーションの数を削減することを可能にします、そして、フェイシャルアニメーションの作成にとっても重要です。

歩行中や走行中に、ターンのため一方に体を傾けるような、キャラクターを作成したいとします。これには、4 つの組み合わせ(歩く-傾く-左、歩く-傾く-右、走る-傾く-左、走る-傾く-右)、それぞれのアニメーションが必要になります。それぞれの組み合わせ用に、個別のアニメーションを作成するのは、このシンプルな事例ですら、明らかに多くの余計な仕事をもたらしますが、アクションが増えると、組み合わせの数はさらに増加します。幸いなことに、加算的アニメーションとミキシングは、単純な動きを組み合わせるための、この個別アニメーションの製作を不要にします。

加算的アニメーションの例

加算的アニメーションでは、 単体のアニメーションを、他の再生予定のアニメーションに重ねて、影響させる事ができます。 Unity は、アニメーションクリップの最初のフレームと現在のフレームの差を計算して、加算的アニメーションを生成します。その後、この差分を再生されているアニメーション全体に適用します。

先ほどの例で言うと、左右に傾斜するアニメーションを作成したら、 Unity 上で歩行やアイドル、走行サイクルに重ね合わせる事ができます。これは、以下のようなコードによって実現する事ができます。

private var leanLeft : AnimationState;
private var leanRight : AnimationState;

function Start () {
   leanLeft = animation["leanLeft"];
   leanRight = animation["leanRight"];

   // 傾斜するアニメーションを異なるレイヤーに加えます
   // ですから、呼び出した CrossFade は互いに影響しません
   leanLeft.layer = 10;
   leanRight.layer = 10;

   // 傾斜するアニメーションを加算的になるよう設定します
   leanLeft.blendMode = AnimationBlendMode.Additive;
   leanRight.blendMode = AnimationBlendMode.Additive;

   // 傾斜するアニメーションを ClampForever に設定します
   // ClampForever を使うと、クリップの終わりに達しても 
   // アニメーションは自動的に停止することはありません
   leanLeft.wrapMode = WrapMode.ClampForever;
   leanRight.wrapMode = WrapMode.ClampForever;

   // アニメーションを有効にして完全にフェードインさせます
   // ここでは、animation.Play を使いません。 Update 関数内で
   // 手動で時間を調整するからです。
   // 代わりに、アニメーションを有効にして重力を最大にするだけです
   leanRight.enabled = true;
   leanLeft.enabled = true;
   leanRight.weight = 1.0;
   leanLeft.weight = 1.0;

   // テストでは、"walk" アニメーションだけを再生し、ループさせてください。
}

// すべてのフレームは、適用する傾きに基づいて
// 正規化された時間を設定します
function Update () {
   var lean = Input.GetAxis("Horizontal");
   // normalizedTime はクリップの最初のフレームで  0、最後のフレームでは 1 
   leanLeft.normalizedTime = -lean;
   leanRight.normalizedTime = lean;
}

ヒント: 加算的アニメーションを使う場合、すでに加算的アニメーションが使われている各トランスフォーム上で、非加算的アニメーションも再生するのはやめた方が良いです。この場合、アニメーションは最終フレームの結果の上に追加されてしまい、全く望まない結果となってしまいます。

キャラクターを手順に沿ってアニメーション

キャラクターのボーンをプロシージャルに動かしたい場合があります。例えば、キャラクターの頭部を特定の 3D 空間座標に向かせたい場合、ターゲットポイントを追跡するスクリプトで制御するのが最善策となります。幸いな事に Unity では、ボーンのトランスフォームでスキンメッシュを動かしているので、これをとても簡単に実現できます。この場合、ゲームオブジェクトのトランスフォームと同じように、キャラクターのボーンをスクリプトから制御するだけです。

ひとつ知ってもらいたい重要な事が、アニメーションシステムの更新は、Update() 関数の変換後と LateUpdate() 関数の前と言う事です。したがって、もし、LookAt() 関数をつかいたい場合、LateUpdate() 関数内で本当にアニメーションが上書きしているのか確認する必要があります。

ラグドールも同じ方法で作成されます。単純にリジッドボディやキャラクタージョイント、カプセルコライダーを各ボーンにアタッチするだけです。これにより、スキン化されたキャラクターが物理演算によって動くようになります。

アニメーションのプレイバックとサンプリング

このセクションでは、 Unity 内のアニメーションがエンジンによって再生される時に、どのようにサンプリングされるか、を説明します。

アニメーションクリップは、一般的に固定フレームレートで作成されます。例えば、3ds Max や Maya では、アニメーションを 60 フレーム / 秒 (fps) で作成できますが、 Unity にそのアニメーションをインポートすると、インポーターがフレームレートを読み取るので、インポートされたアニメーションも 60fps でサンプリングされます。

ですが、一般的にゲーム実行時のフレームレートは変動します。あるコンピューターでは他のコンピューターよりもフレームレートが高いかもしれませんが、次の瞬間には、視界に映っているものの複雑さから、変化してしまうかもしれません。これは、基本的にゲーム実行時の正確なフレームレートを推定するのは困難である事を意味します。つまり、アニメーションを 60fps で作成したとしても、異なるフレームレート、例えば 56.72fps、とか 83.14fps、もしくは全く違う値で再生されるかもしれないのです。

結果として Unity は、可変フレームレートでアニメーションをサンプルする必要があり、そのためにもともと設計されたフレームレートを保証していません。幸いなことに 3D コンピューターグラフィックスアニメーションは、個々のフレームから成り立っている訳ではなく、連続したカーブになっています。これらのカーブは、オリジナルのアニメーション内のフレームと一致しない、任意の時点でサンプルすることができるため、事実、アニメーション製作時より高いフレームレートでゲームを実行すると、アニメーションソフトウェア上よりもゲーム内のほうが、本当にスムーズでより流れるように滑らかなアニメーションに見えるでしょう。

多くの実用的な目的により、Unity がアニメーションを可変フレームレートでサンプルするのを、無効にできます。しかし、トランスフォームやプロパティーに非常に特殊な設定をもつアニメーションに依存するゲーム実行ロジックを使用している場合、シーンの裏側で、再度サンプリングが行われている事を知っておく必要があります。例えば、0 から 180 度まで回転するオブジェクトで 30 フレーム以上のアニメーションがあり、半分に達したときにそれをコードから知りたい場合、現在の角度が 90 度かどうかの確認をコードからするべきではありません。なぜなら、Unity は、ゲームの可変フレームレートのようにアニメーションをサンプルするので、回転がちょうど 90 度のときにサンプルし、次回、また90 度に達した直後もサンプルされてしまうからです。アニメーションが指定した位置に達した通知が必要な時は、アニメーションイベントを代わりに使うべきです。

またこれは、可変フレームレートのサンプリングも同様で、WrapMode.Once を使って再生しているアニメーションでは、正しい最終フレームがサンプリングされていないかもしれません。ゲームの 1 フレーム中では、アニメーションのサンプリングはアニメーションがぴったり終わる前に行われる事があり、その場合、次のフレームはアニメーションの長さを超えた時間上になってしまうので、超えた分はサンプリングされません。アニメーションの最終フレームを絶対確実にサンプリングしたい場合は、アニメーションを明示的に停止するまで最終フレームをサンプリングし続ける WrapMode.ClampForever を使ってください。

アニメーション
旧 GUI