[Unity] ブレンドシェイプをスクリプトで操作する時に気をつけたい事

[Unity] ブレンドシェイプをスクリプトで操作する時に気をつけたい事

Unityネタが続いております、今回はUnityにおけるブレンドシェイプの値をスクリプトで操作する時に特定の条件下では気をつけないと意図した挙動にならないという仕様の話です。

ちなみにBlenderではシェイプキーという言い方をしますが、どちらも同じ機能で、一部の頂点の位置をパラメータを用いて操作できるものになります。

主には表情を変えたりする用途で使われる機能で非常に便利なのですが、Unityの仕様を知らないとドハマリするポイントがありました(実際ハマって頭を悩ませた)。

検証環境

Unityのバージョンは2022.3.56f1になります、最新のUnity6でも同じ動きになるかどうかは不明です。

どの様な場合に問題が発生するか

まず前提となる条件ですが、対象のゲームオブジェクトにアタッチしているアニメーターコントローラー内にブレンドシェイプを操作しているアニメーションが存在し、かつそのブレンドシェイプの値をスクリプトで操作する時になります。

なのでアニメーターコントローラー内にブレンドシェイプを操作するアニメーションが1つも無ければ問題になりませんし、スクリプトでブレンドシェイプを一切触っていなければ今回の件とは無関係になります。

どんな問題が起きるか

簡潔に言うと、アニメーション内で対象のブレンドシェイプを操作していなくても、何らかのアニメーションが再生中、スクリプトでブレンドシェイプの操作ができなくなります

ブレンドシェイプの操作はSkinnedMeshRenderer.SetBlendShapeWeightで可能ですが、これを実行してもブレンドシェイプの値は変更されず、同じ値のままになります。

ちなみに厳密にはスクリプトだけではなく、インスペクター上でも操作が不可能になります。

インスペクターで値を変更すると分かりやすいですが、スライダーを動かしても一瞬で元の値に戻ろうとします。

今再生しているアニメーションはブレンドシェイプの操作をしていないのに、なんで?という感じですね。

考えられる理由

ブレンドシェイプの操作ができなくなる理由は様々ですが、ブレンドシェイプ名を間違えたり単純なスクリプトのミスとかで無ければ、アニメーターコントローラーに登録しているアニメーションのいずれかが原因の可能性が高いです。

というのも、アニメーション内でブレンドシェイプの値を操作するキーが存在する場合、基本的にはスクリプトでの操作が効かないです。

これについては容易に想像できると思います、アニメーション内でブレンドシェイプを操作している訳なので、スクリプトでの操作を受け付けないのは理解できます。

これが罠だなと思ったんですが、例え今再生中のアニメーションでブレンドシェイプを操作していなくても、アニメーターコントローラー内でそのブレンドシェイプを操作しているアニメーションが存在する場合、対象のブレンドシェイプがアニメーターコントローラーの管理下に置かれるみたいです。

これははっきりした根拠は無いんですが、アニメーターコントローラー内で登録しているアニメーションからブレンドシェイプの操作をしているキーを全て削除すると解決する事から、そうなんじゃないか?という結論です。

どうすればいいか

答えとしてはいくつかありまして、まず一番簡単なのは対象のブレンドシェイプをアニメーションかスクリプトのどちらかのみで操作する様に変える事です。

これであれば互いに干渉しないで操作できますし、一番簡単に解決できます。

もしアニメーションとスクリプト両方で操作はしたい、というケースであれば、スクリプト側で操作するタイミングをUpdate関数ではなくLateUpdate関数で行えば可能です。

Unityにおいてアニメーションの反映はUpdate関数後LateUpdate関数前のタイミングになるので、アニメーションでの反映を待ってからスクリプトで上書きする流れになります。

この場合上書きする動作なので、必要無い時にはスクリプトでの操作をしない処理が必要になりますが、これも比較的簡単かと。

上記のリンクはUnity公式のリファレンスにあるイベント関数の実行タイミングについて解説されている内容になりますが、図のGame logicにあるUpdateとLateUpdateの間に「internal animation update」と記載されていますね。

他にも方法はありますが、試したのはこの2通りなので、もしかしたらより良い方法があるかもしれません。

Unityでブレンドシェイプをあれこれ複雑に操作した時には気をつけたほうが良い、という自身に対しての教訓でした。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です