PUBG類ゲームの物理的な衝突の計算方法

今回の主な話題：PUBG類ゲームの物理的な衝突の計算方法、座標が比較的大きい場合のモデルのジッタとフラッシュ、BackBufferのデフォルトサイズの変更、PostProcessingBloomのパフォーマンスコスト。

---
###サーバー同期
Q1: PUBG類ゲームに強同期は必要のため、フレーム同期が使用される場合が多く、クライアントが物理エンジンを直接使用できない場合、またはサーバーが同期状態で衝突を計算する必要がある場合があります。 この時に衝突の部分に対してどうすればよいですか？ データ構造はどうですか？

①
>技術的な解決策を選択できる場合、PUBGのような3D自由視点FPSゲームにフレーム同期を選択することは決してありません。原因は以下になります。
1、射撃ゲームのプレイヤーたちは、動き、射撃などの操作で強い手触りの要求があり、フレーム同期が即時の操作フィードバックをサポートすることは困難です。
2、自由視点なPUBG類ゲームには戦争の霧はありませんが、視距上の問題があります。フレーム同期を使用してすべての情報をプレーヤーたちにブロードキャストすれば、チートプラグインを作るには簡単すぎです。そして、PUBG Mobileなどのゲームで敵の位置を表示するプラグインには大きな利点があるので、本質的に適用しません。

>問題主が言及したフレーム同期が、私が理解しているフレーム同期と一致しているかどうかはわかりません。次に、状態の同期に基づいて、サーバーは物理を実行できます。しかし、実際の物理は完全にサーバー上で実行される場合、サーバーへの圧力が高すぎ、コストが高すぎます。1台の物理マシンも多数の同時オンラインプレーヤーを当れない場合もあります。 実行又は維持用コストが許容できるかどうかを評価するため。よく見られる解決策は：
1）3D物理を単純化し、コンテキスト状態に基づいて、ヒットなどのいくつかのキー判断のみを行います。但し、物理上のデータ計算はより敏感であるため、浮動小数点エラーは一貫性のない結果を引き起こす可能性があります。ここには多くの作業とトラップがあるはずです。
2）3D物理システムの代わりに2D物理システムを使用してそれを行い、物理計算で高さを削除し、特別な検出プロセスと組み合わせて2D衝突のみを行います。これは、実行可能な検出ソリューションの一つであります。
3）クライアントの判断、サーバーの検証、最初にクライアントの判断を信じ、次にクライアントのパフォーマンスを実行し、最後にサーバーがデータに基づいて検証します。ここでは、2D物理エンジンを使用する可能性があり、高さなどの情報をコアな判断に追加する可能性もあります。
4）クライアントの判定、厳格なチートプラグイン防止策、アカウントを停止するなどの手段も追加します。もちろん、プレイヤーの不正行為を判断できる必要があります。判断方法はリアルタイムではなくでも大丈夫です、フレーム同期類似な方法で後に再生して判断しても大丈夫です。この度、3D物理を使用してやる可能性があります。（経験的にはまだ推薦しません、ただリアルタイムからオフラインになります、パフォーマンスへの要求はあまり高くません、3Dを可能になさせます）
5）まずは作りません、ゲームが人気になって、収益化ができれば追加します。人気がなければ、それを台無しにするプロのチートプラグインチームはありません。

>データ構造は細かすぎますので、必要に応じて自分でデザインしてください。 2Dは、オープンソースの2Dエンジンを直接統合すれば大丈夫です。

②
>以下の内容を補充します。

>1）このゲームには、キャラクター以外、ドア、車両、資源など、同期する必要のあるサードパーティの情報がたくさんあります。 フレーム同期の場合、弾丸や消耗品などを同期させる必要もあります。PC端末に対しても膨大な情報量です。 したがって、状態同期を使用する方が現実的です。
2）UnrealEngineに余り精通していませんが、Unreal EngineはNVIDIAのPhysxを使用しています。今、市場にあるPUBG類ゲームはすべてこれに基づいているはずです。では、サーバーがリアルタイムまたはオフラインでPhysxを計算する方法も参照できるはずです。 Overwatchの同期滑らかに関する記事があったと思って、問題主はそれを参照できます。
3）実際、物理的な衝突は大きな問題ではなく、チートプラグインの自動的にねらうと透視が大きな問題です。初期のPUBGは、キャラクターの速度さえ検証もしていませんでしたが、物理的な衝突のためにフレーム同期を使ったら、他の方面に問題がより多くなる可能性があります。

③
>前の皆さんはもう非常によく答えられていると思います。アンチートプラグイン方式を追加しましょう。
最初に、関するクライアントに、元々サーバーで実行する必要のある複雑な計算の結果を送信させ、次に結果、計算、およびパラメーターを複数のクライアントに送信して実行させ、投票検証を行うことができます。これにより、一部のサーバーの負荷を軽減できます。

④
>ValveSoftwareからの技術ドキュメント[「SourceMultiplayerNetworking」](https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking)を追加します。

>この記事も状態同期アーキテクチャに基づいています。 その中で言及されている遅延補償とクライアント入力予測技術は、現在、遅延によって引き起こされる悪い体験に対する主流方法です。


⑤
>PUBG類ゲームのプレイヤーは一般的に100人を超えます。この状況でフレーム同期を使用すれば、同期する必要のあるデータ量は大きくで、遅延もより深刻になります。フレーム同期は通常、同じシーン内のプレーヤー全員の入力を収集し、各クライアントに配布して、各クライアントは同じロジックを使用して各プレーヤーの位置と状態を計算します。ゲームのロジックはクライアントで実行します。MOBAゲームにはプレイヤーが10人しかいないため、フレーム同期に適しています。

>PUBG類ゲームは状態同期に適していると思います。状態の同期では、キャラクターが多すぎることを恐れており、同期する必要のあるキャラクターが多すぎて、ネットワーク同期データを大きくなされます。PUBG類ゲームにはモンスターもいないし、全員プレイヤーなので、シーンにいるキャラクターはプレイヤーであります。取得できるアイテムが同期する必要のデータは少ないで、基本的に位置座標だけでできますが、プレイヤーの状態データの量ははるかに多いです。クライアントが見えないプレイヤーやアイテムの同期する必要が完全にありません。ロジックは完全にサーバー上で実行されるため、クライアントはサーバーのロジックに従って描画するだけで済みます。

>ゲームの手触りに関しては、FPSゲームはすべてのゲームタイプの中で最も高い遅延要件を持っています。プレーヤーのネットワークが悪くと、より良い状況に最適化することは困難です。クライアントは先に表示の予測（たとえば、ヒットされた後の血痕）を行うことができますが、数値結果は依然としてサーバー側の計算に依存しています。そうしないと、チートプラグインに利用されやすいです。サーバーが「ヒットしなかった」と判断しても、大きな問題はありません。ほとんどの場合、プレーヤーは射撃がいくつか当たって、血の効果がありましたが、相手の血は減少していませんでした。この状況は、ほとんど悪いネットワーク環境で発生する可能性があります。

---
###計算精度
Q2: 座標が比較的大きい場合（20000、0、20000）、私たちのプロジェクトには次の2つの問題があります。

1）モデルが移動すると、わずかなジッターが発生します。
2）Androidでカメラを回転すると、モデルがフラッシュします。

Androidのみでこの状況があり、iOSとPCでは正常です。 Unityバージョンは2017.4.2、テストプロジェクトはUWA Q＆Aコミュニティにアップロードされています。

①
>![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/36ad3ff5-65be-d9f8-1167-bcd64a7b1263.png)
http://www.songho.ca/opengl/gl_projectionmatrix.html
NDC空間で、近切断面に近い点のZの精度はより高いで、遠切断面に近い点のZの精度は低いです。遠切断面の値が大きすぎると、Z-Fightingが発生しやすくなります。透視原理に基づいて、この問題は基本的に解決できなく、回避することだけを考えられます。

②
>現有の参照できる方法を補充します：[World Streamer](https://assetstore.unity.com/packages/tools/utilities/world-streamer-36486)

>これは、超大規模なワールドStreamingの完全なソリューションであり、一つのFloating Point Fix機能も実現されています。これは、過大な座標によって引き起こされる精度不十分問題を解決するためのものです。具体的な方法は皆さんがもう言及され、世界の座標を引き戻すということです。さらに、NavMeshには問題があります。最新バージョンのWorld Streamerは、Unity5.6+のNavMeshの動きをすでにサポートしています。 実現コードは、この中のWorldMover.csを参照できます。 使用法については、彼らのドキュメント[「Floating Point FixSystem」](http://indago.homenko.pl/wp-content/uploads/2016/08/World-Streamer-Manual.pdf)を参照してください。

---
###レンダリング
Q3: 私たちのプロジェクトは最適化しています。私たちのプロジェクトは最適化しています。以前には、ゲーム内でシーンを小さいRenderTextureでレンダリングされ、最後にBackBufferに戻されました。しかし、そうするとRenderTextureの余分なコピーが生成されます。

以前の経験から見ると、BackBufferのデフォルトサイズを直接に変更でき、RenderTextureのコピーを回避し、RenderTextureのサイズも縮小できます。UnityがAndroidでBackBufferのサイズを直接変更できるかどうかはわかりません。Unity 5.5.4を使用しています。答えて欲しいです。実には、これは上位バージョンのUnityのDPI設定に似ていますが、現在、Unityバージョンを更新することはできません。
>あるアイデアは、AndroidレイヤーSurfaceのサイズを強制的に変更することであり、可能かどうか又は互換性の問題を検証する必要があります。

>さらに、解像度を下げるとUnityにある出力が存在すると覚えて、ハードウェアスケーリングがサポートされていない場合は、Blitが使用されます。Logcatでの出力は次のとおりです。
``Hardware resolution scaling not supported, falling back to software scaling (blit).``

>関する資料（後半）
https://forum.unity.com/threads/standard-shader-for-mobile.368672

>解像度を直接下げることをお勧めします。Android上のUnityには、ハードウェアスケーリングを試すプロセスがあります。
さらに、Unity 5はAndroid上で常にフルスクリーンのBlitを備えており、BackBufferに直接描画されることはありません。
>備考：https://forum.unity.com/threads/big-performance-issue-with-unity5-on-android.338847

---
###レンダリング
Q4: 了解したいものがあります。PostProcessing のBloomは、1つのLayerだけを開くコストと、すべてのLayerを開くのと同じですか？ポストスクリーン効果なので、レンダリングされた画像を1回だけ処理するので、自分のテストが正しいかどうかを確認したいと思います。
>Githubの公式ドキュメントには次のように書かれています。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/5d40a394-903b-f14d-bc89-0bb4580fef6f.jpeg)
このLayerは、Unityの他の部分のLayerと似ています。Filterとして使用されるため、レンダリング効率は影響を受けませんが、Bloomする必要のないカメラに対しては、ブロックするように設定できます。これにより、効率を向上できます。

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

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