UE5でMMDを踊らせるぞ！

この記事は[Akatsuki Advent Calendar21日目](https://adventar.org/calendars/7459)の記事です。
前日はNaoyaKohdaさんの[ぼくのかんがえたさいきょうのバーチャル美少女配信システム](https://naoyakohda.hatenablog.com/entry/2022/12/20/0000)でした。トラッキングシステムやElixirなど様々な技術を使って実現されていて、バーチャル美少女になるこだわりがとてもすごいですね！

# はじめに
最近Unreal Engineに触れる機会があり、せっかくなので操作に慣れる意味合いで前々からやってみたかったUE上でMMDを動かすということをやってみました。

![MmdUe_-_Unreal_Editor_2022-12-19_19-28-23_-_Trim_AdobeExpress (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/830da30f-a480-5332-338c-279c9128cb7a.gif)


# 概要
記事のタイトル通り、MMDのモデルをUnreal Engineで動かせることを目指します。
やることはシンプルで、MMDをFBXに変換し、UEにインポートしてちゃんと表示できるようにマテリアルを作るだけです。

# 前準備
## Unreal Engineをインストールする
もちろんUEをインストールします。
今回は5.1.0を使用しました。

UEのインストール方法はここでは解説しませんので、公式のドキュメントを参照いただければと思います。

https://docs.unrealengine.com/4.27/ja/Basics/InstallingUnrealEngine/

## Blenderをインストールし、mmd_toolsを導入する

### Blenderの導入
Blenderのバージョンは何でも良い、と言いたいところですが、
3.3系はどうやらFBXに書き出す際にアニメーションがおかしくなるバグがあるようなので3.3系以外のバージョンを使用することをおすすめします。
今回は3.2.2を使用しました。

バグはおそらくこれだと思われる。

https://developer.blender.org/T99876

### mmd_toolsの導入
mmd_toolsはBlenderでMMD用のファイル（.pmx、.vmdなど）を扱えるようにするためのプラグインです。
詳しくは公式のwiki参照してください。

https://mmd-blender.fandom.com/ja/wiki/Home

こちらのバージョンは何でも良いと思いますが、mmd_toolsのバージョンによって対応しているBlenderのバージョンが違うので一度確認しましょう。
今回は執筆時点で最新版である2.8.0を使用しました。
こちらも、導入方法はwikiやgithubのリポジトリを参照いただければと思います。

#### 寄り道: Blender Launcherのすゝめ
上記のBlender 3.3系のバグに付随してBlenderのいろんなバージョンを試したのですが、
Blenderのバージョンを１個ずつダウンロードしてインストールして、というのは大変手間です。

そんなときに使いたいのが「Blender Launcher」
複数バージョンのBlenderを管理する事ができるとても便利なツールです。

https://dotbow.github.io/Blender-Launcher/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/9ac48a56-0282-e2cc-7c7a-ed727eb4c1ae.png)

# MMDをFBXに変換する

Unreal EngineとBlenderの用意ができたところで、早速本題に入っていきましょう。

### MMDのモデルとモーションを用意する

UEで踊らせたいモデルとモーションを用意します。
**！物によってはMMD以外のソフトで動かすことを禁止しているものもあったりするので、使用前に必ずモデル・モーションの利用規約を確認してください！**

今回は「Tda式初音ミク」と「女の子がクルクル回るモーション」を用意しました。
いつ見ても素晴らしいモデルですね！

![test_-_Trim_AdobeExpress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/23b9adb3-0a88-b6da-8982-2dab56d071d8.gif)

### Blenderにモデルをインポートし、物理の設定をする

ファイル > インポート > MikuMikuDance Model (.pmd, .pmx)から用意したモデルファイルをインポートします。
すると3Dビューポート上にモデルが表示されると思います。
表示をマテリアルプレビューにするとちゃんと色も反映されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/8b352b09-5df8-eef0-4067-cec1e7452aae.png)

次に、今回はBlenderで物理挙動をベイクして使いたいのでモデルの物理が有効になるようにします。
UE上の物理や揺れ物を使う際には必要ありません。

3Dビューポートの右上に写っている「<」ボタンをクリックするといくつかのタブが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/417f5551-1a2e-6519-6730-4c094e999263.png)

その中の「MMD」と書かれた部分をクリックすると、mmd_toolsの操作パネルが表示されます。
MMD関連の設定の操作はこのパネルを通して行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/6aad47e3-3203-2be3-3451-d8128457339d.png)

このパネルの中の「組み立て（スパナマーク）」にある「物理演算」をクリックして、モデルの物理挙動を有効にします。
この状態で、Blenderのタイムラインビュー（デフォルトのレイアウトで画面下部）の再生ボタンを押して物理挙動が再生されればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/98290f0f-18bf-62b7-5394-32dac246aa5c.png)

### Blenderにモーションをインポートする
**今度は先程インポートしたモデルを選択した状態で、** ファイル > インポート > MikuMikuDance Motion (.vmd)からモーションファイルをインポートします。
タイムラインビューで再生ボタンを押して、モーションが正しく再生されていることを確認します。

![Blender_2022-12-18_21-19-36_-_Trim_AdobeExpress (1) (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/8cd5c834-5a0c-3943-283c-7e3ab4d777fb.gif)

うまく動いていることが確認できたら、モーションによる物理挙動をベイクします。
mmd_toolsのパネルの「リジッドボディ物理演算」から「ベイク」を実行します。
モーションの各フレームの物理挙動を計算するので、長いモーションだと時間がかかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/1acba786-f638-d7ac-cc66-8029c648d61b.png)

もし物理挙動が必要なかったり、基本的なボーン以外にアニメーションが必要ない場合はベイクは不要です。

### FBXとしてエクスポートする
まず、余計なオブジェクトが書き出されてしまわないよう、必要になるメッシュ、アーマチュア、アニメーションを選択します。
Ctrlキーを押しながら順番にクリックすれば必要なものだけを選択できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/cb6d1a77-0854-7453-bb1c-bd8f2a7fbc7d.png)

この状態で、ファイル > エクスポート > FBX (.fbx)を選択します。
すると、書き出し先のフォルダを選ぶ & 書き出し設定を行うウィンドウが現れるので、ウィンドウ右側にある設定からこのように設定して書き出しを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/934004d4-0928-df3b-33ae-b0ade215c7d9.png)

いくつかの項目について説明します

|項目| 説明|
|:----|:----|
|パスモード コピー<br>（コピーの文字の右の「テクスチャを埋め込むアイコンも選択」）| 使っているテクスチャをFBXの中にコピーします。FBXとテクスチャを分けて管理するのは面倒なので今回はテクスチャを埋め込みました。|
|選択したオブジェクト| シーンコレクションで選択したオブジェクトだけが含まれるようにし、物理用のオブジェクトはFBXに含まないようにします。|
|オブジェクトタイプ| 選択したタイプのオブジェクトだけFBXに含まれるようになります。ゲームエンジンで使う場合には基本的にアーマチュアとメッシュだけで十分かと思います。|
|スムージング| 面か線にしておかないとUEでインポートした際に警告が出ます。|
|リーフボーンを追加| チェックをつけていると、各ボーンの先端に終端ボーンが追加されます。終端ボーンはいらないのでチェックを外します。|

これらの設定を毎回入力するのはかなり面倒なので、「オペレータープリセット」の部分からプリセットとして保存しておくと良いかもしれません。

# 書き出したFBXをUEにインポートする
まずはUEで適当なプロジェクトを作ります。動作確認がしやすいので今回はファーストパーソンを選択しました。
インポートしたいフォルダの中に先程書き出したFBXファイルをドラッグ&ドロップします。
（コンテンツブラウザの「+追加」ボタンからでも大丈夫です。）

するとインポート設定が表示されるのでいくつか設定を行います。

まず「Import Morph Targets」のチェックを付けます。MMDのモーションには人体のボーンのアニメーション以外にもモーフ用のアニメーション（表情やモデルによってはオプションパーツの有効化など）が含まれているので、それらを動かせるようにするための設定です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/444e8eaf-6afe-ea66-18fe-6cab821b43b2.png)

アニメーションを使用したいので「Import Animations」にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/37bce868-9f19-6beb-0dce-a1fd3dc38125.png)

FBXに書き出す際にテクスチャが含まれるようにしましたが、今回はこの後自分でマテリアルとシェーダーを作りたいので、「Do Not Create Material」を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/1d807a00-0259-7c5c-675f-f5635c773196.png)

最後に「全てインポート」を押すとこのようにインポートされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/00915846-c744-fda3-e8c2-1ffadf6beeea.png)

「{書き出したときのファイル名}_Anim」をダブルクリックして開いてみるとアニメーションできていることが確認できます。ちゃんと物理も動いていますね（UEの物理で動いているわけではなく、物理挙動をアニメーションとして動かしている点に注意）。
![miku_Anim_2022-12-18_22-02-53_-_Trim_AdobeExpress (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/1fb285ba-9dc9-e9bc-70b3-d626da40a6bf.gif)

この後使うので、テクスチャもインポートしておきましょう。わかりやすいようにテクスチャ用のフォルダを作って、モデルに付属しているテクスチャをドラッグ＆ドロップすればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/4e70fae7-1a0b-2f5d-4584-f4c88374a698.png)

テクスチャによってはフォーマットが変わってしまうことがあるので、もし色や見え方がおかしくなっていた場合は、
テクスチャをダブルクリックして開いて、圧縮フォーマットやsRGBのチェックボックスを確認してみましょう。
どう合わせればよいかはケースバイケースなのでここでは細かく解説しませんが、ちゃんとした見え方になっている同系統のテクスチャに合わせれば問題ないかと思います。

# マテリアルを作る
インポートするときにマテリアルを生成しなかったので、見た目がグレーでのっぺりしてしまっています。
先程インポートしたテクスチャを貼って終わりにしても良いのですが、
UEは色や質感などのパラメータをいくつか入力するだけでUEらしい物理ベースの表現をしてくれるので、軽くシェーダーを書いてみましょう。

とは言っても、今回は質感にこだわるところはあまり本題ではないので、
MMD側で用意されているテクスチャの解釈をそのまま色として入力して、UEのマテリアルエディターで簡単にできる設定をいくつか行うのみとします。

ではどのようなマテリアルを作ればよいのかということですが、mmd_toolsに付属しているシェーダーを参考にマテリアルを作ってみます。
こちらはBlenderでMMDのマテリアルを選択した状態で、シェーダーエディターを表示すると確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/e23e53bd-8d98-dfb6-2694-84968b6f0d73.png)


## シェーダーのノードを組む

マテリアルエディターの説明や操作は今回は詳しくは解説しないので、公式ドキュメントを参考にしていただければと思います。

https://docs.unrealengine.com/4.27/ja/RenderingAndGraphics/Materials/Editor/Interface/

今回はこんな感じで書いてみました。
|設定| 値|
|:----|:----|
|Material Domain|Surface|
|Blend Mode|Opaque|
|Shading Model|Default Lit|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/eb5f7695-631d-7004-5243-3719708b6994.png)

ざっくり解説すると、MMDのモデルには基本となるテクスチャとは別に、トゥーンテクスチャとスフィアマップというものがあります。
トゥーンテクスチャは影の部分をどんな色で描画するかを指定するテクスチャで、スフィアマップは球面を表現するためのテクスチャで、いわゆるMatcapシェーダーに使うようなものです。

https://w.atwiki.jp/vpvpwiki/pages/216.html


UEではライティングや影は全て付属のパイプラインがやってくれるので、今回はトゥーンは使いません。

### スフィアマップの実装
スフィアマップはMatcapシェーダーのようなものを作ってテクスチャを描画して、それを加算か乗算して使います（MMDをやってた人はスフィア加算、スフィア乗算というとわかりますかね？）
なので、ベーステクスチャとスフィアマップの色をミックスしてベースカラーノードに繋げばそれっぽい色は出せそうです。

スフィアマップのノードの組み方については、こちらの記事を参考にさせていただきました。

https://qiita.com/marv_kurushimay/items/7d49e503f69ba74df427

### ミックスノードの実装
ミックスノード、加算ミックスノード、乗算ミックスノードはBlenderのMixノードを参考に自作したノードです。
それぞれ計算式はこのようにしました。

|ノード|式|
|:----|:----|
|ミックス|A * (1 - Fac) + B * Fac|
|加算ミックス|A + B * Fac|
|乗算ミックス|A * (1 - Fac) + A * B * Fac|

https://docs.blender.org/manual/ja/2.90/render/shader_nodes/color/mix.html

### その他設定ができるようにする
あとは、ものによって半透明だったり、光っていたり反射したりを表現できるように、オパシティノードやエミッシブノードにも最低限パラメータを渡せるようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/8c4c15dc-482f-61b5-3636-74a6df0528e2.png)

## マテリアルインスタンスを作る
このマテリアルを、モデルで用意されているパーツの数だけ生成します。
とは言っても全てのマテリアルに対してシェーダーのノードを組むわけではなく、先程作ったベースとなるマテリアルからマテリアルインスタンスを生成してパーツごとに設定を行います。
先程シェーダーを組んだマテリアルを右クリックして、メニューから「マテリアルインスタンスを作成」を選択し、必要なパーツ分のマテリアルインスタンスを作成してそれぞれテクスチャや値の設定を行いましょう。
使うテクスチャや値はBlenderのマテリアルに設定されているものを参考にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/96fb432c-49aa-7ed9-daeb-291c65d2d751.png)

今回はベースのシェーダーをOpaque（不透明）でDefault Lit（UEのデフォルトの材質）として組んでいるので、
半透明ならBlend ModeをTranslucentに、サブサーフェスを使いたいものはShading ModelをSubsurfaceに、など必要に応じてマテリアルインスタンスごとのBlend ModeやShading Modelを切り替えましょう。


## マテリアルを割り当てる

最後に、先程インポートしたモデルのスケルタルメッシュと書かれているものをダブルクリックして、作ったマテリアルインスタンスをMaterial Slotsにアタッチします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/d3a25025-1d8c-d62f-f3f9-25dc8059f708.png)

**完成！！**
きれいに動いていますね！
![MmdUe_-_Unreal_Editor_2022-12-19_19-28-23_-_Trim_AdobeExpress (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150404/1de2d052-3c31-cdc6-bbc1-409e0510f7e8.gif)

# おわりに
MMDをUE上で動かす上でやることは多いですが、あまり特別なことはせずに実現できたという印象です。
やはりmmd_toolsを作ってくださった方々がすごいですね。
この記事が今後似たようなことをやる方の参考になればと思います。

アデュー

明日の[Akatsuki Advent Calendar](https://adventar.org/calendars/7459)はshivashinさんの「FastDDLを使った高速なmigrationを実施してみた話」です。お楽しみに！！

# 今回お借りしたMMDのモデルとモーション
製作者様ありがとうございました。
Tda式初音ミク・アペンドVer1.10: https://bowlroll.net/file/4576
女の子がクルクル回るモーション: https://bowlroll.net/file/195514