フレーム同期フレームワークでの浮動小数点精度の計算

今回の主な話題：フレーム同期フレームワークでのゲームロジックの浮動小数点精度問題、同じマテリアルを引用しますが、DrawCallバッチの結果は一貫ではありません、Pragma Target 3.0、GC標準。

---
###フレーム同期
Q1: 私たちのゲームはフレーム同期フレームワークを使用しており、ロジックを計算するときに、移動やジャンプなどの浮動小数点計算が必然的に発生します。異なるプラットフォームおよび異なるマシンで一貫した結果を保証するために、浮動小数点数の結果が一貫性のない問題を解決または回避するための良い解決策はありますか？

①
>一般的に、浮動小数点計算に関する位置同期は、高精度を保持する必要はなく、小数点以下2〜4桁を保持するだけで十分です。ですから、計算前に浮動小数点数に1000を掛けて、整数を取得して計算を実行することで、マルチエンド精度の非同期問題を効果的に解決できます。

②
>私たちが研究しているフレーム同期の経験によると、「伝説対決」のようなレベルのゲームではない場合、フレーム同期の浮動小数点精度の影響はシステムのボトルネックではありません。戦闘時間が長くない場合、バレする可能性は非常に低く、全体を整数に変更する作業量は非常に大きくなります。会社は大きくない場合、生き残ることができるかどうかを評価する必要があります。ロジックと表現の分離が最大の問題です、つまり、多数のUnityコンポーネントを使用できません。再実現されたものの多くは最初から作成する必要があり、もちろんすべて整数を使用したいなら最初から作成する必要もあります。小さなゲーム会社に対して、生存と完璧の間に慎重に判断する必要があります。

③
>フレーム同期には固定小数点数の方が信頼でき、浮動小数点数によって引き起こされるエラーは許容できないレベルまで蓄積される可能性があります。他の質問にも答えします。
1）ネットワーク送信に、信頼性の高いUDP（TCP）送信を使用します。
2）さらに、他の人がロジックと表現の分離を言及しましたが、これはフレーム同期に対して必要なものです。Unityの多数のコンポーネントを使用できないということの主な原因は、フレーム同期ロジックをローカル時計の時間に従って処理するのではなく、サーバー時計の時間に従って厳密に処理する必要があるためです。使用できないと言っても、実際には主にロジックレイヤーに対することです。プレゼンテーションレイヤーは、Unityコンポーネントが絶対に利用できないことを意味するわけではありません。プレゼンテーションレイヤーのUnityコンポーネントは実際には不可欠です。

---
###レンダリング
Q2: ShaderのPassに”LightMode” = “ShadowCaster”を追加すると、このオブジェクトに投影と深度レンダリング機能を追加することを意味しますが、”LightMode” = “ShadowCaster”を削除し、Fallbackもoff状態に置いた場合、このオブジェクトをベイクすると（ライトはMixedではなくBakeであり）、シャドウが生成できます。これはなぜですか？
>ShadowCasterは動的シャドウ（Cascaded ShadowMap）のみに使用されますが、ベイクはこのLightModeを使用しません。

>ベイクはMetaというLightModeを使用します、[こちら](https://docs.unity3d.com/Manual/MetaPass.html)を参照できます。

>ベイクシャドウは完全にEnlightenによって計算されるため、一般的なレイトレースベイクの実現から見ると、投影するかどうかはオブジェクトのmeshと透明度に決定します。意外がなければ、metaによって生成された透明度情報がEnlightenで使用され、ShadowCasterを使用してEnlightenに追加情報を生成して渡す必要はありません。

>シャドウをシールドするだけの場合は、スクリプトを使用してオブジェクトにハングアップし、スクリプトを使用してベイクすることを考慮できます。このスクリプトを使用しているオブジェクトがシャドウをオフにすることがわかった場合は、ベイク後に復元すればいいです。

---
###レンダリング
Q3:あるShaderに以下のコマンドを追加しました。

 #pragma target 3.0

では、このShaderがこの特性をサポートしていない場合、自動的にPragma Target 2.0にFallbackしますか？
①
>https://docs.unity3d.com/Manual/SL-ShaderCompileTargets.html

>``When writing either Surface Shaders or regular Shader Programs, the HLSL source can be compiled into different “shader models”. To allow the use of more modern GPI functionality, you must use higher shader compilation targets.``

>``Note: Using higher shader compilation targets may prevent the shader from working on older GPUs or platforms.``

>問題主が自分で理解してください。私の理解と経験では、コマンドまたは特性がサポートされていない場合、FallBackせず、直接ピンク色になります。

②
>これはプログラムの[「Graphics APIの選択問題」（中国語注意）](https://answer.uwa4d.com/question/5b6e3d581e88b37d34e652a1)であります。

>実際に、Shader Target自体はUnityによって抽象化された概念（またはDXのShader Modelを参照して抽象化された概念）であり、実に対応しているものはGraphics APIです。同じに、これもAPIの変更だけでなく、ハードウェア機能の向上も表しています。

>Shader Target3.0のVertexTexture Samplingを使用したい場合は、UnityがShader Target 2.0マシンで自動的にPixelTextureSamplingに変換することは思わないでください。

>もちろん、FallBackを自分で指定するのが最善の方法です。

---
###GC
Q4: 現在、私たちが書いたプログラムはどのバージョンのGCを実行していますか？私はいつもC#のGC原理を、現在作成しているプログラムのGC標準と認識していましたが、今日、Unityには独自のGCがあるという公式ドキュメントを突然見たので、迷惑しました。下記の質問を教えてください。

1）UnityのGCはMonoのGCですか？
2）Monoは.NET標準を実現していませんか？
3）では、MonoのGCもC#のGCの原理であるべきではありませんか？

①
>CLR GCには3つの世代があり、MonoまたはIL2CPPGCは世代を分けません。

>Monoソースコード：https://github.com/mono/mono
現在、Monoが使用しているGCはBenchmark Suite：https://github.com/xamarin/benchmarker

>もちろん、独自のMonoライブラリをコンパイルして、マルチジェネレーションマルチスレッドGC、SGenを使用することもできます。

②
>1）Monoは、初期にはBoehm-Demers-Wiser GCライブラリを使用していましたが、後で世代分け機能とマルチスレッド機能を備えたSGenライブラリに更新しました。
2）強調すべきのは、歴史的な理由から、Unityはバージョンの古いMonoを使用しています。そして、それに基づいて多くの変更を加え、いくつかの新しい周辺機能を統合しているため、最新バージョンのMonoをフォローアップできなくなりました。そのため、GCは依然として最古のBoehm-Demers-Wiserライブラリです。 したがって、最新のMonoを自分で統合しようとする場合、その結果は理想的ではない可能性があります。
3）次に、IL2CPPを忘れないでください。これは完全に独立したRuntimeです。IL2CPPにコンパイルすると、Monoとは関係ありません。この度、独自のGC実現がありましたが、残念ながら、依然として古いBoehm-Demers-Wiser GCを使用しています。
4）Monoは、文法、コンパイル、Runtime、ライブラリなどの方で.NET標準を実行していますが、GCの最下層実現では、少なくとも初期に最下層をどのように実現するのは確定していませんでした。たとえあったとしても、MonoはMicrosoftがコードを開示していないため、当時に、自分で一セットのソリューションを探さなければならなかったので、.NETとは関係のない今のGCの実現があります。

---
###レンダリング
Q5: 教えてください。ゲームシーンのコンポーネントが全部ロードされた後、静的バッチ処理が必要なコンポーネントに対して、統一にStaticBatchingUtility.Combineを一回実行します。ゲーム内のバッチ処理効果と直接にシーン内のバッチ処理DrawCallとは大きく異なることがわかりました。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/14cb095e-0401-c59c-5c38-660ab2f58c41.png)
これらのModelはすべて成功にバッチ処理されており、結果は全部以下の図の示し通りです。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/d495c1dc-a0dc-637d-cac8-347cde825d8b.png)
同じマテリアルを引用し、マテリアル変数も同じでおり、インスタンス化されたマテリアルIDも同じです。2つのDrawCallモデルのMeshもバッチ処理されていますが、提出を二回行い、DrawCallは一つではなく二つあります。
問題はどこにあるのかよくわかりません。シーンで静的バッチ処理を実行した後、シーンDrawCallは約40になり、ゲーム内にシーンをロードした後に静的バッチ処理を一回実行すると、DrawCallは約110になります。
>調査の結果、この問題は静的バッチ処理できないことで引き起こされます。「Objects are affected by different forward lights」と表示されます。さらにテストしたところ、ゲーム内のシーンパーツがポイント光源で照らされ、ForwardAddがバッチ処理を中断することは異なる点であります。ポイント光源がシールドされている場合、バッチ処理は正常です。

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

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