【Unity】LOD(Level of Detail-距離に応じたハイポリ/ローポリの切替)をキャラクターで使用する方法
Level of Detailをキャラクター・・・と言うかアニメーションを持つキャラクターに対して使用する方法についてです。
LOD(Level of Detail)
Level of Detailは距離に応じて描画するモデルのポリゴン数を制御する機能です。近距離のモデルはハイポリ、遠距離のモデルはローポリで表現することで、オブジェクトの描画負荷を低減します。
例えば下の画像は左が通常ポリゴン、右がリダレクション*1を行ったモデルです。近くで見ると右は歪んでいますが、遠距離で見ると左のポリゴン密度が高すぎる点が気になります。
今までの自分の認識ではポリゴン数が問題になる事はそこまで無かったのですが、PBRを綺麗に見せようとすると超ハイポリによる表現が必要な点や、表情を綺麗に変形させたい場合にポリゴン数が多くなりがちな所から、重要度が上がってきてるかなって認識です。
キャラクターとLOD
さてキャラクターに対してLODを実施する訳ですが、もう少し正確に言うならばSkinedMeshRendererをAnimatorで動かすモデルに対してLODを行います。
単純にキャラクターをLODとして表現しようと思った場合、表現それ自体は簡単に設定は可能です。つまり、モデルとAniamtorごとLOD化します。
このアプローチは一見上手く動作するのですが、二つの大きな問題があります。一つはAnimatorを幾つも制御しなければならない点、もう一つはRagdollやFinalIKをはじめとしたボーン制御を使用した機能を使用した場合に破たんすることです。
例えばAnimatorが複数ある場合、単純にAnimatorを複数同時に「同じ内容になるよう」制御する必要があります。
一応LOD対象外の時はアニメーションを行わないよう設計されていますが、Apply Root Motionで動く場合は動いてしまう事、またLOD0とLOD1が違うモーションを行っている場合、LOD切り替えで内容が切り替わってしまう事が問題として上がります。
RagdollやFullbodyIKを行っている場合はもっと微妙です。スケルトンを複数持つのであれば、RagdollやFinalIKを用いるスケルトンと、それに同期するだけのスケルトンを用意する必要があるからです。
つまり今回の回答は、複数のSkinedMeshRendererを単一のスケルトンで表現する事となります。
一つのAnimatorでLOD
やり方は簡単です。SkinedMeshRendererにスケルトンが格納されているので参照関係を構築してやるだけです。
ここでヒントになるのが、ボーンが何処に格納されているのかとAnimatorとAvaterのルールです。Animatorは子階層に一致するスケルトンがあれば操作出来る点(直親で無くても良い)と、SkinedMeshRendererのスケルトンはSkinedMeshRendererが格納している事です。
つまり、こうします。
LODのではなくオブジェクトのRootにAnimatorを持たせ、単一のスケルトンを操作してもらいます。また、各SkinedMeshRendererは同一のスケルトンを参照させます。
要するにメッシュの差し替え(距離)を行います。
やり方
設定手順はこんな感じです。
まずシーンにモデル「Ethan」を配置します。*2
このEthanBody(イーサンの体)とEthanGlasses(イーサンの眼鏡)にSkinedMeshRendererが使用されています。
この二つのオブジェクトを複製します。
複製したオブジェクトEthanBody(1)は、EthanBodyと同じスケルトンへの参照を持っています。これで参照の問題は解決です
後はEthanBody(1)やEthanGlass(1)のSkinedMeshRendererのMeshに、LOD用に用意したローポリモデルを設定します。
この時、同じボーン順番でないと絵が破たんします。もし絵が破たんした場合は、
【Unity】動的にキャラクターの衣装を差し替える - テラシュールブログにあるような形でスケルトンを確認します。
後は親オブジェクトにLODを設定し、EthanBodyとEthanGlassesをLOD1、EthanBody(1)とEthanGlasses(1)をLOD2に設定すればOKです。登録するのはオブジェクトではなくあくまでRendererである点が多分ポイントです。
関連
「見ろ、人がゴミのようだ」の作り方(RagDoll with Unity)