Slide 1

Slide 1 text

/ 14 趣味開発で VRM1.0モデルに 対応した話 2022/12 獏星(ばくすたー) / @baku_dreameater 1

Slide 2

Slide 2 text

/ 14 VMagicMirror (VMM)とは VRMのアバターが動かせるWindows向けソフト。 web / BOOTH ・カスタム表情を含めた、表情を動かすための設定項目がある ・VRoid SDKに対応し、VRoid HubのモデルがDLできる ・目線の動きや揺れものの制御で多少Hackが入っている VRM 1.0モデル対応とは 従来のモデル形式だったVRM 0.xモデルのみを扱える状態から、 VRM 1.0のモデルも読み込んで動かせる状態に移行すること 2

Slide 3

Slide 3 text

/ 14 VRM 1.0対応 in VMM 3 揺れもの 表情 ボーン操作 LookAt ロードAPI VRoid SDK 利用規約UI追加 設定ファイルの 互換性確保 やる 良い感じ エンバグ対策

Slide 4

Slide 4 text

/ 14 ロードAPI etc. ロード関数: VRM10.LoadBytesAsync(byte[], …) ・VRoid SDKはモデルロード関数を↑に差し替えれば大体動く ・ロードしたアバターを保持する型: VRM10Instance ・ロード完了後はVRM 0.xと1.0の区別がつかないが、 メタデータ取得時には判別できる →VRM 0.xと1.0ではモデル規約UIを切り替える UIを切り替えるモチベ (の例): VRM0.xには「政治・宗教利用の許可/不許可」設定はない →無いものは無いので、旧表記にしたほうが実態に合う VRM 0.x 規約(as-is) VRM 1.0 規約(追加) 4

Slide 5

Slide 5 text

/ 14 (補足) ロード直後にやること 自前でランタイム制御のタイミングを制御する instance.UpdateType = Vrm10Instance.UpdateTypes.None; 実際のアップデート: 別スクリプト(ScriptExecutionOrder定義済)でやる class Vrm10InstanceUpdater : MonoBehaviour { void LateUpdate() => instance.Runtime.Process (); } 理由: VMMはScriptExecutionOrderパズルしてる処理が随所にあるため… 通常は自動のアップデートでも大丈夫らしい 5

Slide 6

Slide 6 text

/ 14 良い感じ(1/4) 揺れもの ・VMMには「風」という機能がある ・揺れもの(SpringBone)のgravityにノイズ的な値を加算して実現 ・UniVRM v0.106.0でgravityの追加項だけ指定できるAPIが追加された →追加項に風の成分を入れればOK。 風エフェクトのためのAPIと言っても過言ではない デフォルト + 風の成分 = 合力 デフォルト 風エフェクトの処理イメージ ※UniVRMのSpringBone実装はVRM 1.0でJobベースになった (たぶん昔のより速そう) (知らんけど) 6

Slide 7

Slide 7 text

/ 14 良い感じ(2/4): 表情 (理想編) 表情を制御するAPI ・旧: VRMBlendShapeProxy.(Accumulate | Apply) ・新: VRM10Instance.Runtime.Expression.SetValue 表情の種類(口パク、喜怒哀楽など)を表す型 ・旧: BlendShapeKey ・新: ExpressionKey 関数とデータだけ変えれば良いんだ、ラクだな~ 7

Slide 8

Slide 8 text

/ 14 良い感じ(2/4): 表情 (現実編) 関数とデータだけ変えれば良いんだ、ラクだな~ そんなことはない VRM 0.x向け実装はAccumulate()→Apply()という 関数の呼び出し順序が前提の設計になっている →単に関数だけ差し替えると正しく動かない 結局、VRM0.x向けのクラスである VRMBlendShapeProxy風に動く自作クラスを 挟んで一時的に凌いだ (追加)BlendShapeAccumulator Runtime.Expression ほかのコード群 ExpressionKey, Value Dict 毎フレーム1回呼ぶ 毎フレーム沢山呼ぶ これ 8

Slide 9

Slide 9 text

/ 14 良い感じ(2/4): 表情 (補足) ~表情排他~ VRM 1.0: 表情の排他設定が追加されてる ・各表情に「この表情の適用中は口パク / 目パチしない(or 弱める)」という指定ができる VRM 0.x: ロードすると、表情は全て排他しない設定扱い 例:Happy (旧: JOY)に目閉じモーフが入ってても、Happy/Blinkを同時実行できる 方針: いったん排他設定は信用しないのが簡単 例: Happyの表情を適用中は、アプリ側でBlinkやLipSyncを止める ※VRM 0.x向けアプリでは既にそういう実装が入っているはず ただし、実際には真のVRM 1.0モデルの場合ガード処理を避ける方が見栄えが良い →VRM 1.0の普及前には対策したい… 9

Slide 10

Slide 10 text

/ 14 良い感じ(3/4) ボーン (理想編) 前提: ・VRM 0.x: ボーンのローカル軸はTポーズ状態で全てワールドXYZ軸に揃う ・VRM 1.0: ボーンのローカル軸は元データの軸のまま UniVRMの機能: ・モデルのロード直後、VRM 0.x相当の仮想ボーンを生成してAnimatorを差し替える ・実態はVRM10Instance.Runtime.ControlRig ・Animator.GetBoneTransformすると真のボーンの代わりに仮想ボーンが拾える ・仮想ボーン姿勢に基づいて、(Eye以外の)ボーンが毎フレーム更新 つまりどういうこと?: ・普通にAnimator.GetBoneTransform(…).localRotation = …; で勝手に良い感じになる! ・最高! 10

Slide 11

Slide 11 text

/ 14 良い感じ(3/4) ボーン (現実編) 腕がねじれる!!!Humanoid AnimationとIKの併用で発生 助けて貰いました in : https://github.com/vrm-c/UniVRM/issues/1923 FinalIKで、FBBIK (FullBodyBipedIK)の使い方に問題があった ・詳細はissue先を参照 ・要はIKに対して肩~肘~手首の曲げ方向のヒントを入れると安定する (VRIKとかでは元々やってそう = VRIKだと再現しない) ※ちなみに上記issueの回答適用後も 従来版よりアバターの腕が捻れやすいです。 原因は絶賛調査中… 謎骨折の現場 VRM1.0対応をやめたく なった最大の要因 11

Slide 12

Slide 12 text

/ 14 良い感じ(4/4) LookAt ・VRM 0.x: VRMLookAt ・VRM 1.0: VRM10Instance.Runtime.Gaze ・VMMの場合: 独自処理で目ボーン or 目BlendShapeを制御 ・独自処理のモチベ: 目閉じ制御など △: Animator.GetBoneTransform(…) →仮想ボーンの目が取得できるが、手元だとココをいじっても動かず ※VMMではScriptExecutionOrderをいじりすぎてるせいかも… 〇: VRM10Instance.Runtime.ControlRig.Bones[…].ControlTarget →仮想ボーンではない、モデルのホンモノの目ボーンを取得する Animatorベースでうまく行かない場合でも動く 独自処理の例: 目閉じで目線を下げる →LookAt(Gaze)では表現しきれない 12

Slide 13

Slide 13 text

/ 14 エンバグ対策: 設定ファイル互換性 設定ファイルではBlendShape名をVRM 0.x相当の名称でI/Oしておくように実装 →VRM 1.0対応では何かしら重大バグが起こる前提でダウングレード時の懸念を減らした 13

Slide 14

Slide 14 text

/ 14 まとめ: VRM 1.0対応 やるだけ • ロードAPI / VRoid SDK → やるだけ • モデルの利用規約UIを作る → やるだけ (項目は多い) 良い感じ • 揺れもの → 簡単 • 表情 → APIの互換性に注意 • ボーン → そこそこバグる +まだバグってます • LookAt → 凝ってる場合は要注意 エンバグ対策 • 設定ファイル互換性 → 備えよう 終 獏星 制作・解説 14