Unityでカスタム法線メッシュにブレンドシェイプを適用した際に法線が崩れる問題の解決法

# はじめに
UTS2.0などのNPRシェーダを使ってキャラクターを可愛く見せようとした時、顔メッシュの法線編集は必須になってくると思います。
しかし、Blenderなどでカスタム法線メッシュを作成し、ブレンドシェイプを適用すると、デフォルトではカスタム法線とシェイプキー適用後の法線が競合し、最終的な法線が崩れてしまします。
これではいい感じの陰影が出るように法線を調整していても、ブレンドシェイプを使用して表情が変わった際に陰影がおかしくなってしまいます。

## この記事で書くこと
* カスタム法線メッシュにブレンドシェイプを適用した時に法線が崩れ、陰影がおかしくなる問題の解決法

## この記事で書かないこと
* 法線(Normal)に関する基礎知識
* 法線編集そのもののやり方

# 環境
* Windows 10
* Unity 2018.4.20f1

# 結論
UnityへのFBXファイル読み込み時、`Import Settings`で`Blend Shape Normals`を`None`に設定してください。
これにより、ブレンドシェイプを適用した場合も法線が変化せず、設定したカスタム法線通りの陰影が出ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487269/ad117739-7635-b44e-eb04-3ce961f5399d.png)
以下ツイートを参考にしています。
https://twitter.com/momonoki3000/status/1327679608490061824/photo/1

# 推奨されない方法
以下のように`Legacy Blend Shape Normals`にチェックを入れた場合も、上記画像の設定をした場合と同様にブレンドシェイプを適用した際にカスタム法線が崩れなくなります。
しかし、[上記のツイート](https://twitter.com/momonoki3000/status/1327679608490061824/photo/1)にもありますが、これは**非推奨**のようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487269/8f426367-dc94-4556-8056-7199942ea37b.png)
公式マニュアルを確認したところ、**記載そのものがありませんでした。**
`Legacy`とありますが、ドキュメントに項目を記載する価値すらないということなのでしょうか…。

# Blend Shape Normalsの動作確認
2020年11月時点でのVRChat公式バージョンであるUnity 2018.4のマニュアルによると、以下の記載があります。

> ブレンドシェイプの法線を計算するかどうか、および法線の計算方法を定義します。 Normals プロパティーと同じ値を使用します。

なお、設定値は以下の3つで、マニュアルには説明が記載されていません…。
※分かりやすいようデフォルト値である`Calculate`を一番上に記載しています。

* Calculate (デフォルト値)
* Import
* None

これだけでは動作がわからないため、カスタム法線を適用した自作モデルを使用して動作検証をします。
その他設定はすべてデフォルト値を使用します。

![Setting_PlaneFacial_Rotation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487269/ab11b891-9455-dfeb-cf9d-6a3c399afd28.gif)
ブレンドシェイプを適用していない状態では、FBXに設定したカスタム法線そのままの陰影が出ています。

## Blend Shape Normals : Calculate (デフォルト値)
![NoSetting_Facial_NoRotation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487269/ecef588c-f5d7-b15a-a047-35d93145f816.gif)

### 動作の推測
名称から、ブレンドシェイプ適用後のメッシュ形状に合わせて法線を計算する…というパラメータと考えられます。
それがメッシュに設定されたカスタム法線と競合し、結果として法線が崩れてしまってるのではないでしょうか。

なお、このモデルでは全メッシュを結合しているため、ブレンドシェイプを使用した場合に顔を中心としてモデル全体の法線が崩れ、陰影もおかしくなってしまっています。

## Blend Shape Normals : Import
![Setting_BlendShapeImport_Facial.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487269/68d7663d-4be7-1a68-dff7-29912e328693.gif)

### 動作の推測
`Calculate`では崩れていた耳や腕リボンの陰影は変化しなくなりました。
しかし、カスタム法線を使用した顔の陰影は崩れたままになっています。
どのようなパラメータであるかは、結果からは判断できません…。

## Blend Shape Normals : None
![Setting_Facial_NoRotation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487269/d4ba6082-e0c9-9e1c-2510-ae9f5679f8d4.gif)

### 動作の推測
ブレンドシェイプ適用後もカスタム法線の陰影がそのまま維持されています。
**ブレンドシェイプの法線を使用しない**というパラメータで、ブレンドシェイプの法線がカスタム法線と競合せず、陰影も崩れない…という動作と考えられます。

このため、カスタム法線をブレンドシェイプで崩さないよう、`None`を選択した方がいいでしょう。

## Legacy Blend Shape Normals (おまけ)
余談ですが、この項目にチェックを入れると、動作としては`Blend Shape Normals`で`None`を選択した場合と同様のものになります。
しかし、レガシーという文字、そしてマニュアルに記載がないという部分から、Unityとして非推奨の設定と考えられますので、基本的にこちらではなく`Blend Shape Normals`を使用した方がよさそうです。

# その他設定項目
今回詳細に動作検証はできなかったのですが、[上記ツイート](https://twitter.com/momonoki3000/status/1327679608490061824/photo/1)によると`Blend Shape Normals`以下の設定の推奨値は以下のようになっているそうです。

| 設定項目 | 推奨値 | 設定値の説明 |
|:--------|:----|:----|
| Normals Mode | Unweighted | 法線にウェイト設定はありません。|
| Smoothness Source | None | ハードエッジで頂点を分割しません。|
| Tangents | None | 頂点接線をインポートしません。メッシュに接線がないため、法線マップしたシェーダーとは使用できません。|


自分が動作検証をした限り、`Blend Shape Normals`を`None`にした状態でこれらの設定を変化させた場合、モデルの見た目に変化を確認することはできませんでした。
しかし、「モデルデータの軽さ」という観点ではこの設定にしたほうがデータが軽い…というのはありそうですので、どの設定にしたらいいかわからない、という方はこちらの設定にするのがオススメだと思います。

# 最後に
自分はこれまで非推奨となっている`Legacy Blend Shape Normals`を使用していたのですが、[上記ツイート](https://twitter.com/momonoki3000/status/1327679608490061824/photo/1)を見て検証した結果、公式マニュアルにも記載されないレガシー設定の危うさを知ることができました。
同様に`Legacy Blend Shape Normals`を使用されている方への助けになれば幸いです。

もし間違いや不明点などがありましたら、ご指摘をお願いします。

#参考情報
* https://docs.unity3d.com/ja/2018.4/Manual/FBXImporter-Model.html#geoprops
* https://twitter.com/momonoki3000/status/1327679608490061824/photo/1

#更新履歴
2021/12現在VRChatのUnityバージョンであるUnity 2019.4.31f1.においても本記事の対応に変更はない認識のため、記事を更新。