SIMPLYGONを使ってUnity上でローポリ化してLoDする。

# はじめに

Unityでポリゴン数の多いモデルをそのままインポートしていたら、だんだん性能が遅くなってきたのでローポリ化＆LoD(Level of Detail)をやろうと思いたったのでやりました。

# SIMPLYGONのインストール

Unityでローポリ化する方法を検索するとSIMPLYGONが良さそうな感じです。

https://qiita.com/Futo_Horio/items/d947e45e5c1525c9cddd

環境構築はこちらの記事をほぼそのまま実施すればよいです。私はUnity 2020.3.15f2、SIMPLYGON 9.1、USD3.0.0-exp.1 で試しています。こちらの記事ではUSD2.0.0-exp.1が推奨されていますが、2021/8/29現在ではUSD3.0.0-exp.1で問題ないようです。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1804036/d4c21ec2-8874-addd-a998-46d37a78c59c.png)

Simplygon.Unity.EditorPlugin.dll のコピー先をAssets直下ではなく Editor/Plugins もしくは Plugins/Editorにすることで、ビルド時のエラーを回避することができます。これは、[using UnityEditor; を含むDLLを作るときに気をつけること ](https://qiita.com/GONBEEE_project/items/31e0475ead13bb157710)を参考にしました。

# ポリゴンの削減

正しくインストールできていれば Windows>Simplygon というメニューが存在するはずです。これを開いて、ポリゴンを削減したいオブジェクトを選択します。Add LOD Componentボタンを押してTemplete>Basic>Reductionを選択し、下の方のボタン（黄色い半円２つ）を押すとポリゴンの削減処理が走ります。Run Modeが Run in New Processだと何故かエラーで止まるので、Run in This Processに変更しておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1804036/926e8795-0fd5-efce-543a-be91bf574014.png)

うまく変換できるとこうなります。左が1.9M Trianglesのモデルで、右がポリゴン削減後の0.94M Trianglesのモデルです。正直Wireframeで見ても違いはよくわかりません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1804036/0a7a3591-a585-da2b-1b29-c992a206359d.png)


# 変換時に気を付けるべきこと

変換にはものすごく時間がかかりますので、あらかじめ失敗するケースを知っておくほうがよいでしょう。例えば、選択したオブジェクトの中に、MeshRendererの表示を外したオブジェクトが含まれている場合、Simplygonは何故か表示設定を無視して変換するため、下図のような変換結果になってしまいます。ということで、変換前に不要なMeshRendererを削除することをお勧めします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1804036/67249192-6543-385d-4326-679212314dc7.png)

# 劇的にローポリ化したい場合

Templete>Basic>Remeshing with material baking を選択して変換することで、大まかな形状とマテリアルを維持したまま、非常に軽量なモデルに変換することができます。下図の例では変換後は13858 Triangles、マテリアルは1つに圧縮されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1804036/a8f18723-f38d-0a45-d6a9-d9743fb8a68c.png)

# 穴が開いているモデルの場合

Templete>Basic>Remeshing with material baking だと穴がふさがってしまうため、Templete>Advanced>Remeshing を用いて、Remeshing>Hole Filling をDisabledにすることで穴を維持することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1804036/730448d3-5081-6c46-a69e-abb077e3e0f9.png)

例えば、本体の真ん中にボタン用の穴を残したい場合は、下図のように変換したあと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1804036/279d23dd-bb7d-86ef-f8fe-ae28ba07cf01.png)

ローポリ化していないボタンをはめ込むことができます。このケースでは穴の中にLightを置いてLEDを再現するような実装をしていたので、こういう方法で変換する必要がありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1804036/ed7abfc2-6521-1a93-9e36-b154fb34441f.png)

# LoDの設定

UnityでLoDを行うには LOD Groupを使います。親となるGame ObjectにLOD Groupを設定し、その下に変換したモデルを_LOD0、_LOD1、_LOD2のように名前をつけて管理します。_LOD0を LOD GroupのLOD0にドラッグドロップし、同様に_LOD1、_LOD2もドラッグドロップすることでどのLODの時に何を描画するのかをUnityに伝えます。Gismosを表示することでどのLODを表示しているかが分かるので、あとはカメラからの距離に応じてどのLODを表示すべきかを適切に設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1804036/92b217b1-239d-92e6-fa0a-b4a338926805.png)

LOD1を80%としたときに、LOD0からLOD1に切り替わるのはだいたいこのくらいの大きさです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1804036/8f263c2f-760f-388e-ec54-b9a3ce0712da.png)

# LOD Groupの注意点

LODのモデルが完成してから設定するのであれば問題は起こらないのですが、中途半端な状態でLODの設定をした場合にカメラをいくら近づけてもLOD0にならないとか、逆にLOD0から変わらないというような問題が起こるときがあります。その場合は LOD GroupのRecalculate Boundsボタンを押すと治ることが多いです。Recalculate Boundsで設定した大きさを使って選択すべきLODを判定しているので当たり前なのですが、意外と気づきづらいです。

LOD GroupをアタッチすべきGame Objectにも注意が必要です。RigidBodyで動かす物体の場合は、RigidBodyの親につけてしまうとBoundsが変更されず、LODがおかしくなるのでRigidBodyがついているGame Objectに設定してください。

# さいごに

SIMPLYGONとLODに関しては意外に纏まった情報が無かったのと、罠がいっぱいあったので記事として残しておきます。参考になれば幸いです。