![](https://habrastorage.org/files/e99/f1c/af4/e99f1caf4db1400bafeb0824b8398a77.gif)
手始めに、ちょっとした理論。
Unityには2つのエンティティがあります。
1. アニメーション ([アニメーション]ウィンドウに表示されるもの)
2.アニメーションのメカニズムツリー([アニメーション]ウィンドウに表示されるもの)。
![](https://habrastorage.org/files/8d2/d4b/662/8d2d4b662d28469690e44190d88dcaa5.png)
以下に、それが何であるか、そしてどのように私たちがしなければならない(または役に立たない)かを少しお話しします。
アニメーション
だから、アニメーション。 実際、これはキーフレームのあるタイムラインです。 ここで、オブジェクトを移動、回転、拡大縮小できます。 当然、曲線を描いてさまざまなイシングを使用できます。 さらに、それらのプロパティ(自己記述を含む)を管理します。 つまり、float public値「brightness」を持つコンポーネントを記述し、通常の手段を使用してx、y、zとともにこの「brightness」をアニメートすることは非常に可能です。 スプライトはフレームごとのアニメーションをサポートします。
![](https://habrastorage.org/files/427/ba2/46b/427ba246b8e6433fa939fd09517e6333.png)
ところで、各アニメーションにはFPS(フィールド「サンプル」)があるという事実にもかかわらず、アニメーション自体はFPSにアタッチされていません。 それらは時間に結びついています。 つまり 5 FPSでアニメーションを作成する場合、オブジェクトを最初と最後に2つのキーフレームを設定してポイントAからポイントBに移動すると、ゲームではこのオブジェクトは5 FPSずつ移動しません。 アニメーションはゲームのフレームごとに計算され、アニメーション内のFPSはユーザーの利便性のためにのみ作成されるため、フレームを分割することはありません。
アニメーター
アニメーションを直接制御する大規模で複雑なシステムです。 つまり、アニメーションはキーフレームの設定を持つ単なるファイル(リソース)であり、それ自体は何も知りません。 それがコンポーネント「Animator」です。これが、これらのアニメーションの再生方法を知っているものです。
さらに、これらのアニメーションのツリーを作成し、それらの間でモーフィングを行うことができます。 つまり キャラクターがシフトによってアニメートされている場合(体の各部分が回転/移動する個別のスプライトである場合)、脚のアニメーション、腕のアニメーションを個別に作成することはかなり可能です。 次に、(マウスの助けを借りて)オブジェクトの速度に応じて、メカニカルアニメーターに脚のアニメーションが「歩く」または「走る」という条件を調整します。 また、キャラクターを撮影するために、独立したアニメーションが作成されます。これは、脚を動かす速度とはまったく関係ありません。
最も単純な場合、アニメーターは次のようになります。
![](https://habrastorage.org/files/7dc/04a/02f/7dc04a02fa7a456d943f7f7b36030786.png)
つまり、単一のアニメーションが含まれ、接続/遷移は含まれません。
シャーマンを始めます。
これまでのところ、すべてが明確です。 しかし、もう少し複雑なことをする方法について考えてみましょう。
私の特定のケースは、うさぎが座っている雪の吹きだまりです。 雪の吹きだまり自体が動きます:
![](https://habrastorage.org/files/522/228/d8c/522228d8c95d4e0194de1bb1b70a4270.gif)
次に、このアニメーションを作成します。
![](https://habrastorage.org/files/54b/498/7b3/54b4987b38d34861ba7682b58b98f4d0.png)
1.雪の吹きだまり、移動、左に移動
2.雪の吹きだまりからノウサギがのぞきます(リップルアニメーションが停止します)。
![](https://habrastorage.org/files/e99/f1c/af4/e99f1caf4db1400bafeb0824b8398a77.gif)
3.雪の吹きだまりが右に移動します
原則として、複雑なことは何もありません。 オブジェクト内の雪の吹きだまりの脈動をアニメーション化し、外部アニメーターによってそれを左に移動してから非表示にし、代わりにうさぎのフレームごとのアニメーションを表示し、次に戻します。 そして、これらすべてを1つのタイムラインで(「内部」雪の吹きだまりアニメーションを除く)。
しかし、このオプションはその剛性が好きではありません。 まず、このオプションでは、雪だまりの動きと同じタイムラインにcうウサギのフレームごとのアニメーションが表示されるのは間違っていると思います。 これは、雪の吹きだまりが異なる軌道に沿って移動するこのアニメーションのバリエーションを作成する場合、ウサギのクロールを再びアニメートする必要があることを意味します。 そして、このクロールを修正したい場合、使用されるすべてのアニメーションでこれを行う必要があります。
もっと柔軟性が欲しいです。
別のオプションがあります。 雪の吹きだまりの移動で行ったように、別のオブジェクトでうさぎののぞき見をアニメートし、基本的にこのオブジェクトを適切なタイミングでオン(アクティブ)にすると、アニメーションが開始されます。
これはすでにはるかに優れていますが、それでも完璧ではありません。 実際、この場合、メインのタイムラインで、このクロールのアニメーションの長さを知る必要があります。 適切なタイミングで有効化および無効化する。 しかし、このアニメーションを再び変更し、うさぎがより長く見回した場合はどうなりますか? とにかく、いくつかのより複雑なケースでは、すべてを1つのタイムラインに合わせることがさらに困難になります。
メインタイムラインを一時停止し、添付されたアニメーションの再生を開始し、この添付されたアニメーションの終了時に(またはその中の何らかのイベントによって)一時停止できることが理想的です。
つまり、これを行います:
![](https://habrastorage.org/files/99e/c36/ad1/99ec36ad16a04ae091b81352c4a575e0.png)
1.左に移動
2.脈動する雪の吹きだまりを隠し、うさぎがrawうアニメーションを表示して、一時停止します
3.ウサギのクロールアニメーションを非表示にし、移動する雪の吹きだまりを表示し、右に移動します
これには何が必要ですか? Unityでは、アニメーションにカスタムイベントイベント呼び出しを追加できます。 これはまさに私たちが必要とするものです! すべてを正しく書くためだけに残っています。
最初に必要なことは、単純なコンポーネント(この場合は
GJAnim
と呼ばれ
GJAnim
)を
GJAnim
し、アニメーターがハングするのと同じオブジェクトにハングさせることです。 タイムラインからイベントを呼び出すことができるのは、このコンポーネントのメソッドです。
一時停止のメソッドを作成します。 ちなみに、団結してそのような直接的な機会はありません。 アニメーションを一時停止するには、通常、速度を0に設定して少しダーティなハックが適用されます。通常は動作しますが、奇妙な点もあります(記事の最後の部分で詳しく説明します)。
public void Pause() { _animator.speed = 0; } protected void Resume() { _animator.speed = 1; }
_animator
は、「
Animator
」コンポーネントをキャッシュした変数です。
_animator = GetComponent<Animator>();
上記の画面に注意を払った場合、キーフレームの上に小さな縦線があり、これに数字「2」を付けました。 その背後には、「一時停止」イベント(メソッド)呼び出しが非表示になっています。
![](https://habrastorage.org/files/39f/2c8/8d8/39f2c88d8157460b96992c2ca1f92568.png)
このようなイベントにパラメーターを渡すこともできることに注意してください。 サポートされている文字列、フロート、およびライブラリのオブジェクト(シーンからではありません)。
はい、一時停止しました。 ここで、タスクは一時停止することです。 明らかに、ネストされたアニメーションはこれを行う必要があります。 つまり、うさぎのうさぎのアニメーションが最後まで再生され、イベントが2階の「さらに進む」ことになりました。
public void ResumeParent() { Transform pr = transform; while (true) { pr = pr.parent; if (pr == null) { Debug.LogWarning("No GJAnim found in parents!"); return; } GJAnim a = pr.gameObject.GetComponent<GJAnim>(); if (a != null) { a.Resume(); return; } } }
このメソッドは、親から「
GJAnim
」コンポーネントを検索し、一時停止します。 したがって、このイベントをウサギのアニメーションの最後に配置します。
![](https://habrastorage.org/files/7ba/8e0/fc2/7ba8e0fc2a5c4b018ca5cde601e55367.png)
利益!
実際には、それだけです。 ネストされた/親アニメーションを制御でき、十分な柔軟性を持つ単純なコンポーネントを作成しました。 おそらく、最初の親ではなく特定のアニメーションを一時停止する
ResumeByName(string)
型の別のメソッドが必要です。
さらに、すべてがUnite UI内で行われ、アニメーターにとって十分に透過的です。 私たちのアーティストは、この楽器の手に1時間落ちた後、すでにアニメーション化しています。
Unityのバグと狂気について。
ただし、すべてがそれほどスムーズではありません。 ある時点で、アニメーションを作成すると、アニメーションが正しく動作しないことがわかりました。
一時停止した1つのオブジェクト(他のすべてのオブジェクト)を表示する親(メイン)アニメーションがありました。この時点で、このオブジェクトで独自の(埋め込み)アニメーションが再生され、最後の一時停止から親が削除されました。 次-次のオブジェクトが表示されたなど。
そのため、フレームが時々スキップすることに気付きました。
彼らは長い間議論し、ログに多くのことを書きました...そして、ここに彼らが見つけたものがあります:
どうやら、ユニット内のアニメーションフレーム/イベントのある種のスタックがあります。 コンピューター(ユニティエディター)の速度が低下すると、このスタックに2つのフレームを一度に配置できるため、次の反復で両方のフレームを実行できます。
これには、ほぼ完全に修正できないファイルが必要です。 アニメーターがフレームですべてのアクションを実行して一時停止(これで問題ありません)し、次のフレームも同じフレームで実行された状況をキャッチしました。 つまり、2つのアニメーションフレームが1つのフレームに対して同時にカウントされます。 そして、最初のフレームでアニメーション速度を0に設定するイベントがあったからといって、彼は次のフレームを計算することを止めませんでした。
そして、ウサギのアニメーションで誰もこれに気付かない場合(ウサギは間違った場所のピクセルにクロールします)、何かを非表示にして各フレームを表示すると、ファイルが存在する可能性があります。
現時点では、問題は手に負えないようです。 どうやってやったの? このようなアニメーションのFPSは20になります。どうやら、そのようなFPSでは、ユニットが1回の反復で2つのフレームを計算したい場合は発生しません。
しかし、それでも状況はそれほどではありません。 コンピューター上(または非常に遅いもの)でフリーズを使用しても、プレーヤーはアニメーションの失敗をキャッチすることができます。
これをどうするかは明確ではありません。
シリーズのすべての記事: