2022-02-02 「Animation Viewer」の振り返り
This page is available in English: English
このページは AI(Claude)によって翻訳されています。翻訳に誤りが含まれる可能性があります。
「Animation Viewer」の開発中にいくつかの問題に遭遇したので、ここに記録しておきます。
Animation Viewer が生まれた経緯
Animation Viewer は、私のプロジェクトである ComboGestureExpressions 2(仮称として ComboGestureDynamics とも呼んでいました)の開発中に、偶然生まれました。
アニメーションを CGE の UI にドラッグ&ドロップしやすくしたかったのですが、ドロップする前にアニメーションの内容を確認できないという問題がありました。
その時点で、Animator 上でアニメーションのプレビューを生成する仕組みはすでにありましたが、それは CGE の UI の内部でしか使われていませんでした。
そこで、Project ビュー上で直接アニメーションのプレビューを生成する方法を探し始めました。
失敗したアプローチ:RenderStaticPreview の利用
AnimationClip 型用のカスタム Editor を作ろうとしました。
Editor を実装して RenderStaticPreview メソッドをオーバーライドすれば、マテリアルのように、アニメーションのプレビューをベイクして Project ビューに表示できると期待していました。しかし、思い通りにはいきませんでした。
RenderStaticPreview は、Inspector に表示される小さなサムネイルは更新してくれるのですが、なぜかアセット自体のサムネイルは更新されませんでした。
新しい Texture2D を返すと、アニメーションアセットが変化しなくなります。一方、AssetPreview.GetMiniTypeThumbnail が返す Texture2D を返すと、なぜか空白のアイコンになってしまいました。
さらに、原因のわからないクラッシュが何度も発生しました。
解決策を探すうちに、EditorApplication.projectWindowItemOnGUI コールバックを使う現在のアプローチにたどり着き、これでうまくいきました。この方法では、コールバックの中で項目をキューに追加します。項目が追加されると、次のフレームで、新しく割り当てたテクスチャにキュー内の項目を実際にレンダリングするタスクがスケジュールされます。
回避策:Animator が原点に移動する
プレビューを生成するために、Animator の階層全体をコピーし、元のものを非表示にして、コピーを使って複数のアニメーションをレンダリングし、コピーを削除してから、元のものを再び表示します。
期待される結果は、コピーがその場でアニメーションすることです。しかし、理由はわかりませんが、最初のサンプリングの後に Animator がワールドの原点に移動してしまいます。Animator に RootT や RootQ のプロパティがないにもかかわらずです。
これを修正するために、コピーの位置と回転を記録しておき、サンプリングが終わった後でその位置を手動で再適用しています。
回避策:Muscle が更新されない
アニメーションをサンプリングすると、なぜか、同じフレーム内で続けて AnimatorMode のサンプリングを行っても、Animator の Muscle が更新されません。その結果、すべてのアニメーションのサムネイルが同じ Muscle の位置になってしまい、正しくありません。
これを修正するために、試行錯誤の末、Animator の GameObject を無効にして、同じフレーム内で再び有効にすると、この問題を回避できることがわかりました。