フレーム同期下の移動システムを作成する方法

今回の主な話題:フレーム同期下の移動システムを作成する方法、ブランチ管理の同期問題、カメラスクリーンショットのパフォーマンスを節約する方法、現在のゲームでTextureのMipMap使用レベルを取得する方法、特殊効果の合併問題。


フレーム同期

Q1: 以前、自分でDemoを作ったときに、CharacterControllerと剛体を使って移動する時の壁抜け問題を解決しました。コードはシンプルで効果も悪くないでした。ただし、仕事でフレーム同期のシューティングゲームを作成する必要があります。剛体は表示レイヤーに属すため、マシンごとにパフォーマンスや更新頻度が異なりますから、計算された結果も異なり、非同期を導きますから、使用できません。

現在の方法は、Unity自分のPhysics.BoxCastを使用して行うことです。プレイヤーが入力する時に、衝突ボックスを入力方向に投影し、障害物と衝突して、移動可能な最も遠い位置を計算します。

簡単な地形での効果も悪くないですが、複雑な地形では常にさまざまな新しい問題に遭遇します。自分がゼロから作成するため、いろいろな問題があるはずです。何か関するアルゴリズム、記事、論文、本などありませんか?参考し欲しいです。

表現とロジックの分離はもうできました。プロジェクトは現在、多数の浮動小数点数を使用していますが、徐々に固定小数点数に変更され始めており、固定小数点物理ライブラリも使用します。フレーム同期の問題については、参考になる記事が多く、比較的よく知っています。

質問のあるところは、

1、水平移動と空中360度移動の障害検出とキャラー位置の処理。

2、壁に登る位置、向き、動きの処理。

関連する資料はいつも見つかりませんでした。

私たちのプロジェクトはまだ成熟な物理エンジンを導入していません。すべて自分で書いたアルゴリズムなので、これらの困惑を抱えています。考えなら確かにゼロから全部自分で研究する必要はありません。何かお勧めのUnityで利用できる固定小数点物理エンジンはありますか?

個人的には2つのポイントがあると思います。

1、理想状況では、ロジックレイヤーに1セットの完備な物理エンジンとパスファインディングシステムがあったら、列挙した内容は自然に作成できます。パスファインディングシステムは少し作りやすいかもしれませんが、完備な物理エンジンは一般的に自分で実現しません。基本的には、要件によって具体的な機能を実現します。

2、登りの動作処理に対して、理論的にはロジックレイヤーは動きを注意しなくで、状態のみを注意します。動きは表現レイヤーの任務です。

問題主が言及したこれらの点からみると、問題主が作成しているゲームは非常にアクション向けに感じます。良い操作体験が欲しい場合、本格的なアクションゲームに対して、フレーム同期は最善の方法ではないかもしれません。または、より多い前表現とエラーロールバックを入れるからよりいい体験が得られます。

 

フレーム同期方案については、GithubにあるLockStepFrameworkを参照できます。またはTencentが1セットの解決案は外部に公開しているようですが、連絡して適切かどうかを確認することもできます。同時に、前の人が言ったとおりに、アクションゲームに対して、前表現とエラーロールバックは優れ体験のより大切な点であり、フレームワークを設計するときに事前に考慮する必要があります。

1、フレーム同期には、最初に固定小数点数ライブラリが必要です。これは、ハードウェアプラットフォームが異なると、浮動小数点数の計算結果は違う可能性があるためです。

2、パフォーマンスとロジックを分離する必要があります。

3、自分で1セットの物理ライブラリを実現することをお勧めします。

 

自身だけの移動物理衝突を処理し、他のキャラクターは衝突を行わないことができます。シーン情報(位置、向き、動き)をフレームごとに同期し、適切な予測も行えます。同期する情報の中の位置、向き及び動き(何フレームに)は、タイムラインに再入力できる必要があります。これの実現には非常に簡単です。とりあえず、他のオブジェクトは衝突する必要はなく、自分だけを計算すれば良いです。

もう1つの解決策は、自身を含むすべてのキャラクターがサーバーブロードキャストを使用して行います。事前衝突のために1人の隠すキャラーを作成でき、状態情報をサーバーにアップロードし、サーバーがブロードキャストして表示します。これで、全ての情報を時点で再生できます。これらのメッセージパケットを記録し、再生し、対応する戦略を繰り返し調整するだけで済みます。


Version Control

Q2: 長年私を困る1つの問題があります。

プロジェクトをテストする際、すぐに分岐する必要があります。パッケージを出す後に、ブランチに問題または新しい要件がある場合、トランクからアセットとコードを同期する必要があります。 プロジェクトが大きくなり、機能が増え、チームが大きくなるにつれて、同期は非常にめんどうくさいことになります。

私たち現在の開発や同期のプロセスは非常に原始的です。全員がメイントランクを開発し、テストやリリース用バージュンが必要な時、ブランチを開きます。ブランチの要件とバグは、メイントランクで開発されています。更新する必要がある場合は、コードとアセットをブランチに同期し、再びパッケージします。

コードは1人にまとめされ、アセットは別の人にまとめされます。機能開発に関する全員は1つの「同期グループ」に属し、同期するコンテンツを固定形式でグループに送信します。開発が完了した後、実際に同期する場合は、全員から送信された同期内容に応じて、同期を担当する2人が少しずつ同期します。

このやり方の問題は明らかです:

1、同期はいつもこれらの2人で、1人はクライアントの責任者であり、もう1人は同期を管理するPMで、人材の無駄になります。そしてコードもすべて同じで、毎回同期する時に長い時間がかかります。そうなんに多いコードが同期するため、長い時間の後に目まで痛くなります。

2、エラーが発生しやすい。

a.同期する人に対して、開発者と同じ人ではないから、同期にエラーが起こしやすいです。

b.開発する人に対して、一部の機能はかなり前に開発されていますが、同期する必要がある場合に、何を同期するかを思い出せません。振り返って確認する必要があり、これもエラーが発生しやすくなります。

皆さんは同じような困ることがありませんか?何かより良いプロセスありませんか?何か提案をしたり、自分のプロジェクトのプロセスについて話したりしていただければ幸いです。ありがとうございます。

私たちのGitのプロセスは、

1、継続的な開発プロセス全体でmasterは基本的に必要ないため、masterを使用しなくなりました。

2、主な開発ブランチはdevであり、テストされたすべての新しい機能はdevにマージします。

3、各人は、機能と責任に応じて、可能な限り詳しいが完全な若干featureに割り当てされ、ローカルでfeatureブランチを作成して開発を行います。人々には若干featureを同時に行えますが、多すぎるのはお勧めしません。そうしないと、管理の難易度が高くなります。サーバーの中に中間プロセスのブランチが多すぎるのを避けるように、出来る限りにローカル開発ブランチをサーバーにアップロードしません。featureの期間が長い場合、または他人数の協力が必要な場合を除きます。

4、featureを開発過程には、機会を探して(毎日またはいくつのキーノードに)devを自分のfeatureブランチにマッジする必要があります。自己ブランチの機能が最新、衝突が最小を確保します。

5、featureが開発完了、リリースつもり時にはdev→feature→devのマージプロセスに実行し、featureをdevにマッジする必要があります。

6、マッジするfeatureを一定期間に保存して、後で変更及びロールバックやすいようにします。一定期間後(通常は機能がリリースする後)、ローカルfeatureブランチを削除して、ブランチが増えるのを防ぎます。

7、リリースする時に、今回リリースつもりのある毎人のfeatureを1つずつに5の方式でdevにマッジして、テストを始まります。内部ネットテストに通過すると、このdevから新しいブランチを開き、名前はリリース予定日となり、そしてこのブランチで外部ネットテストとバグ修正を行い続きます。

8、リリース用ブランチでbugを発見や修正し、問題の開発者がdevへマッジします、通常はcherry-pickを使います。他の人は、またdevで自分のブランチと開発を行います。

9、アセットに関して、通常、我らは機能開発に向け、アセット管理に専任の人員を分ません。したがって、機能の開発者は、機能に関するすべてのアセットとコードを完全に掌握する必要があり、責任をとってアセットとコードをアップロードして問題の解決を同期します。

10、プロジェクトの開発者全員が上手に使用できるように、権限とプロセスを可能な限りに割り当てます。ミスを許し、ミスから学びます。誰でもプロセスを進めることができれば、人事異動による作業の中断を回避できます。


Render

Q3: 現在のプロジェクトでは、1秒間に30回スクリーンショットを撮るカメラが必要です。しかし、ReadPixels関数を使って1秒に30回コールしたらパフォーマンス消費が高すぎます。何かそれを置き換える方法はありますか、それとも、他のパフォーマンス消費の低いスクリーンショット方法はありますか?教えてください!感謝します。

Unityのバージョンが比較的にあ新しい場合には、1つのAsyncGPUReadback機能があり、スクリーンショットに助かれます。ReadPixelsより早いですが、1秒間に30回コールすれば、また多くのパフォーマンス消費があります。

このオープンソースライブラリの例を見ることができます:

https://lab.uwa4d.com/lab/5b5a5659d7f10a201fe4c4e0

スクリーンショットを撮ると、出力を外部に保存したい場合には、Windowsプラットフォームに対して、全画面をキャプチャするより高速な方法があり、これは、Desktop Duplicationキャプチャテクノロジです。この速度は非常に速く、まるでビデオとほぼ同じです。

このオープンソースライブラリの例を見ることができます:

https://lab.uwa4d.com/lab/5b563fb5d7f10a201fd8d0de


Texture

Q4: 現在の一枚テクスチャのMipMap使用Levelを取得したいのですが、Unity 2017.4には対応するAPIがありません。他に取得できる方法はありますか?

レンダリングで使用されるMipMapレベルは、テクスチャごとではなく、ピクセルごとに異なります。これにより、Shaderのfragment階段でこれを取得できるはずです。AssetStoreでMipMapを表示するツールがいくつありますが、すべて見積もりです。UnityがもたらすScene Viewモードの計算方法がわかりません。ソースコードが見つかったら、それを参照できます。検索すれば方法が見つけられらしいです。具体的にはしていませんが、方向はddxとddyに基づいて計算されているように感じます。


DrawCall

Q5:このような特殊効果では、4つのノードがあり、各ノードが1つのShaderと1枚のテクスチャを使用しています。4つのDrawCallに相当します。

同じシェーダーなので、マッジすることを考慮しています。ただし、私たちのテクスチャには、他の特殊効果も利用しているかもしれません。これは、これらのテクスチャを1枚のアトラスにマッジしたら冗長性がありまあす。マッジしないとDrawCallが高いですが、マッジするとメモリが高くなります。皆さんがこのような状況に何か良いアドバイスがありませんか?特に特殊効果に関するものです。

「私たちのテクスチャには、他の特殊効果も利用しているかもしれません。これは、これらのテクスチャを1枚のアトラスにマッジしたら冗長性がありまあす。」って言いましたけど、君らの特殊効果テクスチャは一般的にどのサイズですか?小さいなら一枚のアトラスにより多い特殊効果をマッジできます。例えば、共有テクスチャにあり、事前ロードすることのできるほうを一緒にマッジし、依頼関係パッケージを行います。

さらに、決定に役立つデータを取得することをお勧めします。例えば、戦闘中にある特殊効果のDrawCallとメモリ状況や、全体的なDrawCallとメモリ状況など。当時では、DrawCallのほうが厳しいですが、またはメモリのほうが厳しいですかを判断できます。


UWA公式サイト:https://jp.uwa4d.com

UWA公式ブログ:https://blog.jp.uwa4d.com

UWA公式Q&Aコミュニティ(中国語注意)https://answer.uwa4d.com