今回は作ったモデルを Unity を通して VRM 化する手順について書いていきます

普段使っている LightWave には、標準で VRM 出力する機能がありません

この場合はUnity の力を借りる必要があります
※Blender ならアドオンで VRM 出力出来るっぽい

これまでは MMD 向けのモデルを作ってきたので、ボーンの構造がまず違います

そのままでは正常に認識されません

ただ、ボーンの構造を Humanoid と同じにすれば正常に認識して変換できることが分かりました

ボーン名やウェイト名が MMD と同じでも問題無いようです

今回はただの VRM 出力テストなので、表情の割り当てはしないです

まずは簡単なことからということで、内容を書き残していきます

準備

まずはいろいろと準備から

Unity をインストールする

STEP1
UnityHub をインストールする

まずはUnity のアカウントを作成して、自分の OS に合ったものをダウンロードします

自分は Windows ユーザーなので、 x64 をクリックしてダウンロード&インストールしました

STEP2
エディターをインストールする

次にエディター

ここではLTS(長期サポート)である 6.3 LTSをインストールしました

もっと新しいバージョンもありますが、予期しないエラーが出る可能性があるので、成熟したバージョンを選びます

STEP3
プロジェクトを作成して起動する

プロジェクトは Universal 3D で作成します

プロジェクト名も必要なら分かりやすいものに変更して、「プロジェクトを作成」を実行

起動まで長いので固まったかのようになりますが、しばらく待ちます

VRM 化パッケージをインストールする

ここまででとりあえず Unity はインストールと起動ができたと思います

ただ、素の状態では VRM 化するための機能が備わっていないので、機能追加します

以下の GitHub から VRM 化用のパッケージをインストールしていきます

VRM には

  • VRM 1.0系(ファイル名:VRM)
  • VRM 0.x系(ファイル名:UniVRM)

の二種類あるので、自分が作りたい方の unitypackage をダウンロード

じゃっく

自分の場合は VRM 1.0 用をダウンロードした

ダブルクリックしてパッケージを起動

チェックが全部入っていることを確認して、そのままインポート

うまくいくと画面上部に

  • UniGLTF
  • VRM1

の項目が追加されます

これで Unity 側の準備は OK

ボーン名や構造を VRM 向けにする

STEP1
ボーンやウェイト名を整理する

モデル側の方ですが、ボーンの構造が Humanoid 基準にさえなっていれば、MMD 基準の名称でも一応出力できることが分かりました

ただ、今後のことを考えて他のアバターで使われているに名称変更

じゃっく

ちょっとめんどかった

Humanoid 基準の名称は以下サイトからとって、少しアレンジを加えました

https://docs.unity3d.com/ja/2023.2/ScriptReference/HumanBodyBones.html

STEP2
ボーンの構造を VRM 用にする

ここからボーンの構造を VRM 向けに変えていきます

これまでは MMD 向けな構造だったので

  • center
  • eyes
  • leg_IK
  • toe_IK

などがありましたが、VRM(Humanoid)では不要なので、これらは削除

同時に下半身にあたる lower_body は VRM で言う所の Hips にあたるので、一旦切り取りして 180° 回転させて先端のポイントを結合します

念のため、SkelegonEditor を開いて Spine(元upper_body)の親子付けを再設定しておきます

これで Hips が最上位になり、VRM(Humanoid)と同じ構造になります

構造は以下になりました

Humanoid ボーン構造
  • Hips
    • Spine
      • Chest
        • Neck
          • Head
            • Head_end
            • Eye_L
              • Eye_L_end
            • Eye_R
              • Eye_R_end
        • BustBase_L
          • Bust_L
            • Bust_L_end
        • BustBase_R
          • Bust_R
            • Bust_R_end
        • Shoulder_L
          • UpperArm_L
            • LowerArm_L
              • Hand_L
                • Hand_L_end
                • ThumbProximal_L
                  • ThumbIntermidiate_L
                    • ThumbDistal_L
                      • ThumbDistal_L_end
                • IndexProximal_L
                  • IndexIntermidiate_L
                    • IndexDistal_L
                      • IndexDistal_L_end
                • MiddleProximal_L
                  • MiddleIntermidiate_L
                    • MiddleDistal_L
                      • MiddleDistal_L_end
                • RingProximal_L
                  • RingIntermidiate_L
                    • RingDistal_L
                      • RingDistal_L_end
                • LittleProximal_L
                  • LittleIntermidiate_L
                    • LittleDistal_L
                      • LittleDistal_L_end
        • Shoulder_R
          • UpperArm_R
            • LowerArm_R
              • Hand_R
                • Hand_R_end
                • ThumbProximal_R
                  • ThumbIntermidiate_R
                    • ThumbDistal_R
                      • ThumbDistal_R_end
                • IndexProximal_R
                  • IndexIntermidiate_R
                    • IndexDistal_R
                      • IndexDistal_R_end
                • MiddleProximal_R
                  • MiddleIntermidiate_R
                    • MiddleDistal_R
                      • MiddleDistal_R_end
                • RingProximal_R
                  • RingIntermidiate_R
                    • RingDistal_R
                      • RingDistal_R_end
                • LittleProximal_R
                  • LittleIntermidiate_R
                    • LittleDistal_R
                      • LittleDistal_R_end
    • Hip_L
      • Hip_L_end
    • UpperLeg_L
      • LowerLeg_L
        • Foot_L
          • Toes_L
            • Toes_L_end
    • Hip_R
      • Hip_L_end
    • UpperLeg_R
      • LowerLeg_R
        • Foot_R
          • Toes_R
            • Toes_R_end

各オブジェクトとボーンを一つにする

STEP1
各マップを確認

作ったモデルに、以下のマップが用意されていることを確認します

  • UV マップ
  • モーフマップ
  • ウェイトマップ

モーフマップとウェイトマップの作り方は過去記事にあります

出力するだけならモーフマップは無くても大丈夫でしたが、UV マップは必須だったので忘れずに作っておきます
おまけに理由を書きました

STEP2
サーフェイスを設定する

各部位にサーフェイス(マテリアル)の設定をしておきます

設定しなくても特に出力には影響しません

ただ、ちゃんと設定しておいた方が融通が利くことが分かったので、ここは設定しました

じゃっく

マテリアルは standard か Principled BSDF にします

STEP3
ボーンとオブジェクトをまとめる

あとはボーンとオブジェクトを一つにまとめて、まとめたレイヤーのみを読み込むように設定して保存します

保存後はレイアウトにぶん投げます

本体を正常な変形ができる状態にする

レイアウトに飛ばしたら SkelegonReader でボーンを正式なボーンに変換

変換後は「中心点回転記録」を忘れずに実行します

あとはボーンの最上位である Hips を右クリックしてボーンを全選択

ボーンプロパティから

  • ウェイトのみ:オン
  • 固定長の長さで乗算:オフ

に設定して、体が動かせる状態まで持っていきます

これで一通りの準備が整いました

手順

ここからが VRM 化していく手順です

こんな感じになりました

モデルを FBX で出力する

モデル本体を選択した状態で出力から「 FBX ファイル出力」を選択して、画像のように設定します

Unity に FBX を読み込む

Unity 側では Assets の中に新規フォルダを作って管理しやすいようにします

その中に先ほど出力した FBX ファイルをポイっと突っ込みます

リグの設定をする

STEP1
リグを Humanoid に変更&設定する

作ったモデルの FBX ファイルを選択した状態で画面右側の Inspector に

  • Rig
  • Model
  • Materials
  • Animation

の四つが表示されているので、その中のRigを選択

Animation Type が Generic になっているので、ここを Humanoid に変換

STEP2
リグに問題が無いか確認する

変換後は Apply を押して適用

適用後は Configure を押してボーンが正常に割り当てられているか、念のために確認します

じゃっく

たまにアゴに全然違うものが割り当てられていたりする・・・

Jaw と Upper Chest はオプションなので、特に割り当てが無くても問題ありません

確認後は画面右下の Done を押して設定から抜けます

FBX を VRM 出力する

STEP1
ヒエラルキーにモデルを取り込む

FBX ファイルを画面左のヒエラルキーにポイっと投げ込みます

問題が無ければモデルが表示されます

STEP2
VRM モデルのメタデータを入力する

後はモデルを選択した状態で VRM 化パッケージを導入した時に現れた VRM1 から Export VRM1.0 を実行

必要なメタデータを入力します

  • Name:モデルの名前
  • Version:バージョン名
  • Authors:作者名

さらに画面下へ行くと商用利用の可否とかを設定できますが、今回はただのテスト出力なので、そのあたりは適当です

結果

結果はこちら

VRM10Viewer で確認しました

ちゃんと認識されましたし、動いていますね

じゃっく

予め入っているモーションが面白い

これで変換完了です

まとめ

では、まとめを簡単に

まとめ
  • Unity バージョンは LTS 推奨
  • UV 展開は忘れずにやっておく
  • ボーン名は無理に変えなくても OK
  • ただしHumanoid 基準にした方が良いかも
  • ボーン構造は Humanoid への組直しが必要
  • VRM 0.x と 1.0 で使うパッケージ名が違うことに注意

今回はLightWave から Unity を通して VRM 化する方法をやってみました

最初は MMD ボーンの構造を変えないといけないのかとちょっと身構えましたが、やることは

  • 不要なボーンを削除する
  • ボーンの構造を Humanoid にする

という二点だけだったので、意外と簡単な処置で問題無く VRM 化できました

なので、最初は MMD 用に作って後から VRM 用にする手順にすれば、比較的お手軽に二種類のモデルが作れます

じゃっく

逆だとちょっと面倒かも

今回はコンストレイン?とか揺れ物無しの簡単なローポリモデルで試しましたが、将来的にはもっと実用的なモデルでやってみようと思います

それではお疲れさまでした~

おまけ

UV は展開しておかないとエラーを出す

これはもっと簡単なモデルで VRM 化しようとした時に起きたエラーです

じゃっく

モーフとUV無しのやつ

UV マップを作らずに無理矢理出力しようとすると

  • NullReferenceException: Object reference not set to an instance of an object

と言うエラーを吐きました

たぶん何らかのオブジェクトの参照ができないみたいなことを言っているんだろうなと思いました

が、正直このエラーが一体何を指しているのかさっぱり分かりませんでした

じゃっく

もう全く分からん

そこで完成形に近い状態として適当に展開した UV マップを作成したところ、あんなに悩んでいたエラーが嘘のように無くなったので、原因を特定できました

同時に モーフの有無はあまりこのエラーには関係ないことが判明

恐らくですが、どうやら UV マップが無いと自動的に割り当てられる要素が無くてエラーを吐いていると予想しています

VRM 0.x 系では起きなかったエラーと記憶していますが、VRM 1.0 系になったことでチェックが厳しくなったようです

今後もモデルの作成には注意したいところであります

参考資料

使用ツール

3DCG
  • Unity
  • LightWave3D
動画
  • Bandicam
  • ScreenToGif
画像
  • CLIP STUDIO PAINT PRO