Unityのアニメーションシステムによって,素晴らしく生き生きとした快活なキャラクター作成が可能です。アニメーションシステムは,アニメーションのブレンド,ミキシング,加算的アニメーション,歩行周期の同期,アニメーションのレイヤー,アニメーション録画再生の全体にわたった側面の制御(時間,速度,ブレンド-重量),1,2か4ボーン分の頂点にメッシュスキニングだけでなく,物理ベースのラグドールと,手続きアニメーションもサポートしています。最良の結果を得る為に,最適化されたキャラクターモデリングページの最も良い練習とUnity内にオプション演出を伴ったリグキャラクタの作成技法について,を読む事をおすすめします。
快活なキャラクター作成には, 動き 一貫した世界と アニメーティング 振る舞い2つの事が含まれます。もう少し動くキャラクター周りついて学びたいなら,キャラクターコントロールページに目を通してください。このページはアニメーションに焦点をあわせています。事実上,キャラクターのアニメーティングはUnityのスクリプトインタフェースを通して行われます。
快活なキャラクターの事前設定を公開しています。実例デモでダウンロードできます。このページで基礎を学んだ後,アニメーションスクリプトインタフェースを参照することも出来ます。
こんにちのゲームは,アニメーションのブレンディングが,キャラクターをスムーズにアニメーションすることを保証する,必要不可欠な機能になっています。アニメーターが,例えば,歩く繰り返し,走る繰り返し,アイドリングのアニメーションか射撃のアニメーションとアニメーションを分けて作成します。ゲーム中のどの時点でも,アイドルアニメーションから歩行サイクルまたはその逆へと,望みの移行をすることができます。当然,スムーズにし突然の急な動きは避ける移行を望んでいます。
ここでアニメーションのブレンディングの出番です。Unity内では,同じキャラクター上のアニメーション再生の番号をいくつも持つ事ができます。全てのアニメーションは,混ぜたか追加した,共に最終のアニメーションで生成します。
最初のステップは,アイドルから歩行アニメーションへの,なめらかなキャラクターブレンド作成が出来る様にすることです。スクリプターの仕事を楽にするため,最初の設定をアニメーションのWrap ModeをLoopにします。その時,ひとだけアニメーション再生するスクリプトか確めるためにPlay Automaticallyをオフにしておきます。
最初のアニメーティングキャラクター向けのスクリプトは,割と単純です。どうやって早くキャラクターが動いているか,見いだすための方法のみ必要です。その後,歩くからアイドルへゆっくりアニメーションします。簡単なテストのために,標準の入力軸を使う事にします:-
function Update () {
if (Input.GetAxis("Vertical") > 0.2)
animation.CrossFade ("walk");
else
animation.CrossFade ("idle");
}
あなたのプロジェクトで,このスクリプトを使うには:-
プレイボタンを押すと,キャラクターは,上の矢印キーを押し続けで場所内を歩き始め,離すとアイドルポーズに戻ります。
レイヤーは,グループアニメーションと重み付け優先順位を付けることで,非常に有用な概念です。
Unityのアニメーションシステムは,いくつでもアニメーションクリップの間をあなたが望むだけ混ぜる事ができます。マニュアルで重みを混ぜて割り当てるか,単にanimation.CrossFade()が使えます,どちらのアニメ化も重みは自動的に行われます。
例えば,歩く繰り返しと走る繰り返しが在ったとします,両方とも1(100%)の重さを持っています。 Unityが最後のアニメーションを生成する時,それは正規化された重さになり,歩く繰り返しのアニメーションに50%を与え,走る繰り返しにも50%が与えられる事ということです。
ですが,2つのアニメーションを再生する時,どちらのアニメーションがより多くの重みを受けるか,一般的に優先順位が欲しいでしょう。確かに手動で100%の重さにすることは可能です,しかし,この目的ではレイヤーを使うだけ方が簡単です。
例として,射撃アニメーションが,アイドルと歩行サイクルに在るかもしれません。歩行とアイドルのアニメーションは,プレイヤーが射撃するとき,プレイヤの速度基準にブレンドされますが,射撃アニメーションのみを見せたいでしょう。従って,射撃アニメーションは本質的に高い優先順位を持ちます。
これを行う簡単な方法は,単純に射撃中に歩行とアイドルアニメーション再生し続けることです。これを行うには,射撃アニメーションが,アイドルと歩行アニメーションより高いレイヤー内に,作成されているか確認する必要があります,つまり射撃アニメーションは,最初の重さ配合を受けるであろうことを意味します。射撃アニメーションが100%,重みの配合を使っていない場合に限り,歩行とアイドルアニメーションは,重さを受け取る事ができます。そんなわけで,射撃アニメーションでクロスフェーディングするとき,重さはゼロから始まり短い期間で100%に近づきます。最初のうちは,まだ歩行とアイドルレイヤーが配合された重さを受けとりまが,完全に射撃アニメに移行したときには,全く重みを受け取りません。これは,まさに我々が望んだものです!
function Start () {
// Set all animations to loop
animation.wrapMode = WrapMode.Loop;
// except shooting
animation["shoot"].wrapMode = WrapMode.Once;
// Put idle and walk into lower layers (The default layer is always 0)
// This will do two things
// - Since shoot and idle/walk are in different layers they will not affect
// each other's playback when calling CrossFade.
// - Since shoot is in a higher layer, the animation will replace idle/walk
// animations when faded in.
animation["shoot"].layer = 1;
// Stop animations that are already playing
//(In case user forgot to disable play automatically)
animation.Stop();
}
function Update () {
// Based on the key that is pressed,
// play the walk animation or the idle animation
if (Mathf.Abs(Input.GetAxis("Vertical")) > 0.1)
animation.CrossFade("walk");
else
animation.CrossFade("idle");
// Shoot
if (Input.GetButtonDown ("Fire1"))
animation.CrossFade("shoot");
}
デフォルトのanimation.Play()とanimation.CrossFade()は,停止したり,同じレイヤー内にあるアニメーションをフェードアウトします。これは,まさに我々が最も望んだ状況です。射撃,アイドル,走る例において,アイドルと走るの再生は,射撃アニメーションに影響しないと言え,またはその逆の場合も同じです(望むならこの振る舞いは,animation.CrossFadeのオプションパラメータで変更できます)。
アニメーションミキシングは,いくつかのアニメーションを身体の一部のみに適用することで,ゲーム作成に必要なアニメーションの数を削減することを可能にします。これは,そんなアニメーションが他のアニメーション内の様々な組み合わせと共に使えることを意味します。
AnimationStateが与えられたAddMixingTransform()を呼び出すことにより,アニメーションへアニメーションミキシング変換を追加する。
ミキシングの例は,ひょっとすると手を振るアニメーションの様なものかもしれない。キャラクターがアイドルのときか歩いているときのいずれかに,手の振りを作成したいかもしれません。アニメーションミキシング無しでは,アイドルと歩行状態のために手を振るアニメーションを分けて,作成しなければならないでしょう。ですが,もし,肩の変換へ手を振るアニメーションをミキシング変換などで追加するなら,手を振るアニメーションは,肩の関節から手まで全てを制御するしかないでしょう。手を振ることで,体の残りまで影響を受けることはなく,アイドルか歩行アニメーションを続けて再生します。その結果,体の残りがアイドルか歩行アニメーションで使われている間は,唯一のアニメーション作成,手を振るが必要になります。
/// Adds a mixing transform using a Transform variable
var shoulder : Transform;
animation["wave_hand"].AddMixingTransform(shoulder);
もう一つの例,パスを使用する
function Start () {
// Adds a mixing transform using a path instead
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"];
// Put the leaning animation in a separate layer
// So that other calls to CrossFade won't affect it.
leanLeft.layer = 10;
leanRight.layer = 10;
// Set the lean animation to be additive
leanLeft.blendMode = AnimationBlendMode.Additive;
leanRight.blendMode = AnimationBlendMode.Additive;
// Set the lean animation ClampForever
// With ClampForever animations will not stop
// automatically when reaching the end of the clip
leanLeft.wrapMode = WrapMode.ClampForever;
leanRight.wrapMode = WrapMode.ClampForever;
// Enable the animation and fade it in completely
// We don't use animation.Play here because we manually adjust the time
// in the Update function.
// Instead we just enable the animation and set it to full weight
leanRight.enabled = true;
leanLeft.enabled = true;
leanRight.weight = 1.0;
leanLeft.weight = 1.0;
// For testing just play "walk" animation and loop it
animation["walk"].wrapMode = WrapMode.Loop;
animation.Play("walk");
}
// Every frame just set the normalized time
// based on how much lean we want to apply
function Update () {
var lean = Input.GetAxis("Horizontal");
// normalizedTime is 0 at the first frame and 1 at the last frame in the clip
leanLeft.normalizedTime = -lean;
leanRight.normalizedTime = lean;
}
ヒント: 加算的アニメーションを使っている時は,それは いくつか他の非加算的アニメーションで常に変換する加算的アニメーション内で使われるそれでも再生でも重大で,さもなければ,アニメーションは,最終フレームの結果の上に追加されることになります。これは最も重大な望んでいないことです。
時には,あなたのキャラクタのボーンを手順に沿って動かしてみたくなります。例えば,ターゲットの位置をトラックするスクリプトで,3D空間の目標位置にあなたのキャラクターの頭が追従するのに最善な方法はどれかと思うかもしれません。幸いな事にUnityは,これらをとても簡単に作成します,ボーンからどのスキンメッシュが動いて変換するだけかだけです。従って,GameObjectのTransformの要領で,スクリプトでキャラクターのボーンを制御できます。
ひとつ知ってもらいたい重要な事が,アニメーションシステムの更新は,Update()関数の変換後とLateUpdate()関数の前と言う事です。従って,もし,LookAt()関数をつかいたい場合,LateUpdate()関数内で本当にアニメーションが上書きしているのか確認する必要があります。
ラグドールは同じ方法で作成されます。単純に,キャラクタージョインと異なるボーンのカプセルコライダへRigidbodyをアタッチする必要があります。これで,キャラクタの皮膚は,物理的なアニメーションをすることができでしょう。
このセッションは,プレイバックエンジンでサンプルした時に,どのようにUnity内でアニメーションするのかを説明します。
アニメーションクリップは,一般的に決められたフレームレートで生成されています。 例えば,3ds MaxかMayaでアニメーションを60秒割るフレーム(fps)のフレームレイトで,作成できます。Unity内にアニメーションをインポートするとき,このフレームレートは,インポーターで読まれ,インポートされたアニメーションのデータは,おおよそ60fpsにサンプルされます。
しかしながら,一般的なゲームの実行においてフレームレートは変動します。フレームレートは他に比べコンピュータ上で高くてよく,そして,一秒から次のカメラが与えられた瞬間に見ている視点の複雑さに基づくまでも,そうかも知れない。要するに,ゲーム実行時に正確なフレームレートが作成できるという前提ということです。これが意味することは,もしアニメーションを60fpsで生成されていたとしても,それは,例えば56.72fps,か83.14fps,もしくは事実上違う値など,異なるフレームレートで再生されるでしょう。
結果として,Unityは,可変フレームレートでアニメーションをサンプルする必要があり,そのためにもともと設計されたフレームレートを保証していません。結果として,Unityは,可変フレームレートでアニメーションをサンプルする必要があり,そのためにもともと設計されたフレームレートを保証していません。幸いなことに,3Dコンピュータグラフィックスアニメーションは,別々のフレームから成り立っている分けではなく,むしろ連続したカーブなっています。これらのカーブは,任意の時点でサンプルされる事があり,それだけで無く,その時点のオリジナルのアニメーション内のフレームでも一致しません。実際に,より高いフレームレートで生成したアニメーションでゲーム実行すると,アニメーションは,ゲーム内で,アニメーションソフトウェアでそれをしなかった場合より,本当にスムーズでより流れるよう見えるでしょう。
最も実用的な目的のために,Unityサンプルアニメーションで可変フレームレートを事実,無効にできます。しかしながら,ゲーム実行ロジックが,アニメーションの変換かプロパティに非常に特殊な設定のアニメーションに頼っている場合は,シーンの裏側で,再度サンプリングが行われている事を知っておく必要があります。例えば,0から180度まで回転するオブジェクトで30フレーム以上のアニメーションがあり,半分に達した時にそこをコードから知りたい場合,もし現在の角度が90度なら状態のに関する確認をコードでするべきではありません。なぜなら,Unityサンプルは,ゲームの可変フレームレートのようにアニメーションし,回転が丁度90度より下の時にサンプルされ,次回,90度に達した直後もサンプルされます。もし,アニメーションが達した時に通知の必要がある場合,AnimationEventを代わりに使うべきです。
またそれは,可変フレームレートをサンプリングの結果と同じようで,アニメーションつまり,再生で使っているWrapMode.Onceは,最終フレームの正確な時間にサンプルしていないかもしれない。アニメーションの終わりちょうど前のサンプルしたかもしれないゲームアニメーションのいちフレーム内では,次フレームの時間はアニメーションの長さを超えることができる,なので無効になり,よりいっそうサンプルされないです。正確なサンプルされたアニメーションの最終フレームを断固として必要な場合,WrapMode.ClampForeverを最終フレームをいつまでも保持するサンプリングになるだろうが,自身でアニメーションを停止するまで,使用する必要があります。