プラナリアのメモ

BlenderとかVRChatとかVRoidとかの覚え書き

そもそも何故VRChat Avatars3.0で表情が戻らない現象が起こるのか(およびWrite Defaultsへの呪詛)

はじめに

Write Defaultsを許すな

 

この記事はVRChat SDK3(Avatars3.0)製VRCアバターの表情が変えたら戻らない/表情が混ざるバグ、および物を出したら戻らない現象
はたまた左右の表情が変に混ざる現象について
UnityのAnimator Controllerの仕様から説明する記事です。

 

質問・指摘はhttps://twitter.com/InPlanariaまで

 

手っ取り早く表情バグを直したい人は以下の記事を見てください。

inplanaria.hatenablog.com

 

 

参考文献

tsubakit1.hateblo.jp

docs.unity3d.com

docs.google.com

 

 

Write Defaultsとは何か、何が問題なのか

まずWrite Defaultsってオフとオンどっちがいいの?

よっぽど特別な理由がない限りオフ推奨

VRChat運営もオフにしろって言ってる

docs.vrchat.com

 

でもWrite Defaultsオフを条件に発生するバグもあったりする

  • GestureレイヤーのHumanoid以外のTransformアニメーションがVRC上で反映されない
    →Humanoid外TransformはFXレイヤーにアニメーションを移せば一応動く
  • Write Defaultsがオフだとアニメーション付き椅子に座った時うまく動かない

 

じゃあWrite Defaultsってなんだよ

例えると「壊れた補助輪」

Unityの用意した便利機能のはずだったがVRChat環境との相性が最悪

 

WriteDefaultsとは本来どういう機能なのか

「デフォルトの状態」に戻すのを勝手にやってくれる存在。

f:id:InPlanaria:20211022185101p:plain

f:id:InPlanaria:20211022185111p:plain

上記はブレンドシェイプEye_Closeを動かすアニメーションを使い、目を閉じる表情を表示した例。
アニメーションの再生をやめ、Eye_Closeを動かすアニメーションをひとつも再生していない状態になった場合、「オブジェクトをデフォルトの状態に戻す」。これがWriteDefaults機能である。

 

WriteDefaultsは何が狂っているのか

一見便利そうなこの機能をなぜ使ってはいけないのか。
何かの拍子に「デフォルトの状態」を勝手に忘れやがるからである。(詳しい条件は参考文献参照)

f:id:InPlanaria:20211022185229p:plain

f:id:InPlanaria:20211022185359p:plain

クソWriteDefaultsに頼っているとこんなことになるので、VRC公式はWriteDefaultsを使うなとお触れを出したのである。

 

なぜWriteDefaultsオフだと表情が混ざるのか

しかし、今までWriteDefaultsに頼りっきりであったアバターが何も対策せずWriteDefaultsオフにした場合、あの現象が起こる。

f:id:InPlanaria:20211022185556p:plain

f:id:InPlanaria:20211022185602p:plain

WriteDefaultsがオフの場合、Eye_Closeを動かすアニメーションがない状態になってもオブジェクトがデフォルトに戻ることはない。
このまま、ブレンドシェイプEye_Smileを動かして笑顔の表情を表示しようとすると…

f:id:InPlanaria:20211022185726p:plain

こんな風に表情が混ざり破綻するのである。

 

 

WriteDefaultsオフでも正しく動かすにはどうすればいいのか

簡単な話、「アニメーションが何も再生されていない状態」を避けるだけでいい。

f:id:InPlanaria:20211022185556p:plain

f:id:InPlanaria:20211022190316p:plain

Eye_Closeを100にするアニメーションを表示したあとは、Eye_Closeを0にするアニメーションを表示する。
そうするだけで、アバターの顔は元の状態に戻ることができる。

これがWriteDefaults対策でデフォルト顔のアニメーションをわざわざ作る理由である。

 

表情が戻らない現象だけでなく、物を出したら消えない現象にも同じことが言える。
物を出したら消えないのは、「物を出す」アニメーションだけ作って「物を消す」アニメーションがどこにもないからである。

とにかく「アニメーションで何かを動かしたら、元に戻すアニメーションもあとで再生する」それだけを意識すればいい。

 

 

 

「表情が戻らない現象の直し方」では何をしているのか

Animator Controllerのレイヤー処理順の仕様

冒頭で紹介した「表情が戻らない現象の直し方」。
作ったデフォルト顔のアニメーションは、一番上のレイヤーに入れることになっている。

なぜならレイヤーの処理順は上から下だからだ。

f:id:InPlanaria:20211022191016p:plain

 

Defaultsレイヤーがデフォルトに戻すアニメーション、Left Hand レイヤーが目を閉じるアニメーションを表示している場合の動作はこんな感じである。

f:id:InPlanaria:20211022191259p:plain

 

Left Handレイヤーがアニメーションの再生をやめた場合、Defaultsレイヤーがデフォルト顔アニメーションを再生してデフォルト状態に戻してくれる。

f:id:InPlanaria:20211022191641p:plain

 

もしデフォルト顔を入れた一番上のレイヤーが存在しなかった場合、「何も再生しない状態」になってしまい、顔を元に戻すことはできない。

f:id:InPlanaria:20211022191553p:plain





 

余談:左右の表情が変に混ざる原因

f:id:InPlanaria:20211022193150p:plain

Left HandレイヤーでEye_Smileを100、Right HandでEye_Closeを100にしていた場合。
何も考えずに作ると、このように表情が混ざって破綻する。

 

f:id:InPlanaria:20211022193240p:plain

左右の表情が干渉する問題の対策は様々である。
例えば上図のようにRight HandレイヤーがEye_Smileを0に上書きしてしまえば、最終結果はEye_Close=100,Eye_Smile=0となり破綻しない。

「左手は口だけ、右手は目だけを動かすと決めて干渉し合わないようにする」
「Right Handsレイヤーの一つ上に、右手表情表示中だけデフォルト顔アニメーションを出すレイヤーを置いておく」
「左右のハンドサインによる表情をひとつのレイヤーにまとめておく」
といった対策も考えられる。

 

 

表情が戻らない現象の直し方には別解もあるという話

ここまで読んだ人にはもうお分かりであろうが、デフォルトレイヤーを増やす以外にも現象への対処法はある。
「どの表情アニメーションでも、すべてのブレンドシェイプを使うようにする」ならば、どの表情を表示しても全ブレンドシェイプが動くので「戻らない現象」は回避できる。

ただし全表情アニメーションを編集しなおすのは面倒なので、デフォルト顔アニメーションを一個作るだけで済む手法がおすすめされるわけである。

 

少量の物の出し入れギミック程度なら、全アニメーションを修正したほうがわざわざレイヤー新設するよりスマートかもしれない。