ナビメッシュ情報導出

今回の主な話題：「ナビメッシュ情報導出」、「LoadLevelAsyncロード効率」、「IL2CPP使用後のMonoメモリ理解」。

---
###ロード
Q1：携帯でLoadLevelAsyncとLoadLevelのロードスピードをテストします。同じシーンで、LoadLevelAsyncはLoadLevelより40％くらい長く時間をかかります。これは正しいですか。LoadLevelには重い時があるのため、Loadingプログレスバーがスムーズではないが、LoadLevelAsyncを採用したらLoading時間が増えるはずです。
プロジェクトに動的シーンをロードする私のやり方は、オブジェクトをPrefabにします、使ったのはResources.LoadAsyncです。今にも、大きなオブジェクトをロードする場合、Red mi 2のようなローエンドモデルではまだ重っています、200ms以上かかります。ですからこのロードをスムーズするために、何かいい方法ありますか。
>一般的にLoadLevelAsyncはLoadLevelより時間かかりますが、40％遅いかどうかは、次々のシーンがロードすべき量で決定します。定数ではありません。
実は、LoadLevelとLoadLevelAsync最も根本的な違いは、前者は必ず次のフレームが終わる前にロードを完成させます。だからシーンが大きい時、後の単フレームコストも大きくなります。後者にはこのような限制はありません。エンジンは現在の使用状況やThreadPriority（この値はLoadLevelAsyncに影響あるかどうかはまだ実験されていませんけど、確かにLoadAsyncに影響があります）により、自分で調整できます。しかし、Asyncを使ったら、絶対にスムーズになることではありません。下記の図に赤枠にのはLoadLevel、緑枠にのはLoadLevelAsync操作です。
![１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/cbc5458f-ae62-1aed-71e1-d88b802c4621.png)
本格的な「スムーズ」非同期ロード方式のは、今のUnityエンジンにはありません。複雑なPrefab（大きなテクスチャや複数のAnimationClipなど）にあう時、ロードにまだ重い状況はあります。もしこの問題を解決したいなら、UWAからのアドバイスは：
1.先に具体的にどちらのPrefabロードのCPU時間コストは高いかを特定します。
2.このPrefabに時間のかかる動作（大きなテクスチャ、複数のAnimationClipまたはシェーダーなど）が多いかどうかを確認します。
3.特定された動作を前期プリロードすることを試み、Prefabロード時の一部分の高コストを解決します。

---
###メモリ
Q2:私はIL2CPPを使った後、Monoメモリはもう存在しするか。IL2CPPを用いて,Profilerツールで取得したmanagedObject(int32[]など)はどのようなメモリですか。
>簡単に認められるのは、IL2CPPはただMonoの仮想マシンの実現を取り替えました。だからMonoメモリを配分すべき場所は同じように配分します（些細なディテールは違うかもしれません）。Monoメモリ配分にIL2CPPとMono最も違うのはReserved Totalは低下できます、MonoのReserved Totalは上昇のみ低下できません。

---
###レンダリング
Q3：シーンが自動的にベイクしたナビメッシュ情報はNavMesh.assetの中に保存されてあります、開くと下記のようなデータが見られます：
![deta.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/43c64599-0b83-61e0-8422-02bfb1c416fd.png)
プロジェクトはサーバーでロケーションする必要があり、できる人にこのデータの解析やレセt用のナビメッシュへの還元を手伝っていただきたいです。Unityバージョンは5.5.１です、Unity4.2にこの解析コードはありましたけど、新版には様式は変わりました。
>まずはNavMesh.CalculateTriangulationですべての頂点と索引データを取得します、これは完全な、構築したNavMesh、多辺形情報（最大辺数は６の凸多辺形）が含まれてあります。しかしこのデータにのすべての多辺形の辺は共有していません（多辺形の辺は重複のデータ）。ですからまずは重複の辺を合併します、RacastNavigationが提供したコードを利用できます、rcBuildPolyMeshに基づいて一つの修正版を作って（例えばrcBuildPolyMeshBySeparatePolyTriangleと呼ぶ）、目的は既有の多辺形の重複の辺を合併します。これが終わったら、RacastNavigationが残った構築流れを利用できます：
1.NavMeshを作成し,以上のPolyMeshを用いて初期化します(dtCreateNavMeshData,dtNavMesh::Init)。
2.既存のNavMeshによるエンクロースボックスを更新します。
3.既存のNavMeshに従って、一つ一つのTileをファイルに書き込みます(その前にカスタマイズされたヘッダ情報を書き込むことができ、読み取りやすくなります)。
4.サーバーに蓄積されたデータを読み込み,初期化してNavMeshを生成すると、findpathが行えます。(このデータをRacastNavigationのDemoに導入し、可視化状況を見ることもできます)。

>以上の1〜4はRacastNavigation例で流れ構築の一部です、重点はrcBuildPolyMeshBySeparatePolyTriangleで多辺形を合併すればいいんです。このような利点は,導出されたNavMeshとUnityに構築されたNavMesh,多辺形は同じです。DetailMeshに支持するのは、まだできませんらしいです。
また,サーバを直接利用するには問題があるかもしれないが,Unityが導出したデータが細長い三角形のものが多い場合,RacastNavigationの結果がUnityと大きく異なり,RacastNavigationのコードを少し修正する必要があります。

---
###レンダリング
Q4：現在、私が使用しているUnityバージョンは2017.1.0f3 for MACであり、iOSプラットフォームでBake Environment Reflectionsを行う際にHDR情報を失いました。操作手順は下記のように：
⑴Standalone Platformを使ったとき、HDR付きSkyBox CubeMapマップ(デフォルト圧縮方式BC6H)を使いました。生成されたReflectionProbe-0.exrは対象に顕著なハイライトを与えます。
![２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/3d104be9-6439-9b2b-3faa-a658bdb70db2.png)
⑵iOS Platformに切り替えた後,再び同じSkyBox CubeMapパッチ(圧縮方式はPVRTC, 圧縮しないRGB24 bitも試みた)でReflectionProbe−0.exrをベイクすると,この効果は消えました。
![３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/22829ff8-dd05-cbd5-11ab-f7521da8146f.png)
⑶このとき,私が前のStandaloneが生成したReflectionProbe−0.exrを置き換えますと,Standaloneと同様のハイライトが得られます。これをiPhone 7Plusで動作させますと,「ステップ⑴」と同じ効果が得られます。ReflectionProbe-0中のHDR情報は保存されましたと分かりました。しかし、iOS Platformでは、ReflectionProbe−0のデフォルト圧縮方式はPVRTCやRGB 24 bitであり,どちらの方式もHDR情報を保存できません。
![４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/91b119b9-d35f-b7df-d104-90e7d328be4d.png)
⑷2枚のReflectionProbe−0.exrスタンプを比較しますと、ファイルのサイズは違う、Standaloneのスタンプの方がちっと大きいです。これはUnityのBugですか。
![11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/0a744dde-e6f0-c167-66e6-999ac2c087c2.jpeg)
こちらに私が例のプロジェクトexr_EnvRef_iOS.zipをアップロードしました。デフォルトはPC Standaloneで、Platformを手動的に切り替え、後に再びGenerate Lightingの必要があります。

①
>問題主のプロジェクトファイルを使ってみました、確かに同じ問題が出てきました、そしてAndroidでも同様です。今から見るとReflection-Probeがベイクされた時２セットの異なる操作が使われているとしか判断できません。
もう一つの手がかりを提供します、renderdoc−>texture viewerで画素値を見ることができます。
![５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/350ac310-6762-7478-9866-ba6ca5772612.png)
Standalone（PC）
![６.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/8b0fdbf7-6f72-d463-1643-5e12e2ae566d.png)
Android
上の図から分かれるのは、似たようなエリアに対してStandaloneのベイク結果の値はAndroidより高いです。

②
>Unity5.6で効果は同じと発見しました、結論は問題主と同じです：MobileプラットフォームでベイクされたのはLDRなProbeです。彼は輝度を高めましたが、実にはもっと簡単な方法があります：高mipを見ればいいです。まずはPCでの効果です。
![７.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/6f443b9a-141e-2587-4d47-33060f6d3e23.png)
そしてAndroidでの：
![８.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/bb580b15-08b0-2c8a-45c6-3057b132eed2.png)
輝度上の違いはPCでは輝度＞１画素（一般的には太陽など）があり、畳み込み時の値は大きくなりました；Androidでは相対的に低いです。Mip＝0の場合には誰も０−１ですから見えません。今の結論はモバイルプラットフォームでベイクされたのはまだLDRなProbeです。これは間違いです。暫定的な解決策はStandalone でベイクしたらコピーします。

③
>問題主からの補充：新しい発見はありました、ほぼbugが確認できます。2枚のreflectionProbe—0.exrスタンプは確かに違います。サイズ以外、iOSプラットフォームに切り替わった後に生成されたexrは、ハイライト部分のHDR情報を失っています。
![12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/a4c8a2be-fa64-a1f3-a636-03fb0912f2a0.jpeg)
一見するとこの2枚の画像は同じですが、
![13-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/4990bcfe-d63f-1ddc-ccf5-8da73897673e.png)
exposureを調整し,exposureを−5にする(openexrを用いたが,psを用いて直接曝露度を調整することも可能です)。
![14-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/2657dc42-cfad-88d0-94f0-f7efc999f2be.png)
上図には2つの 鮮明なスポットが見られますが,このスポットは非常に明るいため,物体に強いライトを生成できます。しかし、iOS Platformでベイクするとき、Unityはこの情報を失ってしまいました。ただし,すべてのexrにこのような問題が生じるわけではありません、局所的に強力な光源を持つHDR画像だけが現れます。

---
UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、**パフォーマンス分析**と**最適化ソリューション**及び**コンサルティングサービス**を提供している会社でございます。

UWA公式サイト：https://jp.uwa4d.com
UWA公式ブログ：https://blog.jp.uwa4d.com