doc: use professional translation for README.ja.md

JakeTheJake74[0] generously donated a professional translation of
this document (not by me). We use it to correct the old one.

[0] https://github.com/pond3r/ggpo/issues/2#issuecomment-546357632
This commit is contained in:
Silvan Jegen
2019-10-26 19:36:10 +02:00
parent 80b8800fa2
commit 755121085e

View File

@@ -1,90 +1,101 @@
# GGPOとは何か
# GGPOとは
2009年に作成されたGGPOネットワーキングSDKは、ピアツーピアゲームでのロールバックネットワーキングの使用を開拓しました。 非常に正確な入力フレームの完全な実行を必要とする速いペースの単収縮スタイルのゲームでネットワーク遅延を隠すために特別に設計されています
2009年に開発されたGGPOネットワーキングSDKは、ピアトゥピアゲームにおけるロールバックネットワーキング実用化の先駆けとなったシステムです。正確な入力や、フレームごとの完璧な処理を必要とし、ゲーム展開が速くかつ配信に適したゲームにおいて、ネットワーク遅延を目立たなくさせることに重点を置いて開発されました
従来の手法では、プレヤーの入力に遅延を追加することでネットワークの送信時間を考慮し、結果としてゲームの動きが鈍くなります。 ロールバックネットワーキングは、入力予測と投機的実行を使用して、プレーヤーの入力を直ちにゲームに送信し、ゼロ遅延ネットワークの錯覚を与えます。ロールバックネットコードを用いて、プレイヤーがオフラインでプレイすることで蓄積した筋肉のメモリ、タイミング、リアクション、およびをビジュアルキューとオーディオキューオンラインでも直接に利用できます。 GGPOネットワーキングSDKは、ロールバックネットワーキングをできるだけ簡単に、新規および既存のゲームに組み込むことができるように設計されています。
従来の技術はプレヤーの入力に遅延を織り込んで通信を行っており、その結果反応が遅く、ラグを感じるプレイ感になっていました。ロールバックネットワーキングはプレイヤーの入力を即座に送信するため、入力予測と投機的実行を行うことにより、遅延ゼロの回線環境をもたらせるのです。ロールバックがあれば、タイミングや相手の動きや効果音に対しての反応、指が覚えている入力、これらオフラインで行えた内容が、そのままオンラインでも行えます。GGPOネットワーキングSDKは、ロールバックネットワーキングを新作や発売されているゲームに極力簡単に組み込めるよう作られています。
# 仕組みは
# どう動作する
ロールバックネットワーキングは、完全に決定的ピアツーピアエンジンに統合されるよう設計されています。完全決定論により、単に同じ入力をフィードするだけで、すべてのプレイヤーコンピューターで同じ方法でゲームがプレイされることが保証されます。これを実現する1つの方法は、ネットワーク経由ですべてのプレヤー入力を交換し、すべてのプレヤーがピアからすべての入力を受け取ったときにのみゲームプレイロジックフレーム実行することです。そうすると、多くの場合、結果としてゲームプレイの反応が遅く、応答が遅くなります。ネットワークを介して入力を取得するのに時間がかかるほど、ゲームは遅くなります。
ロールバックネットワーキングは決定的ピアトゥピアエンジンに統合できるよう設計されています。 完全決定的なエンジンなら、同じ入力をした場合にゲームは必ず同じ内容のプログラム再生をします。 その内容を実現するつの方法としては、ネットワーク上に全プレヤー入力をやりとりをする方法があげられますが、これは全プレヤーがピアから入力を受け取った時にゲームプレイロジックが1フレームだけ実行する形になります。 この方法ではゲーム内でキャラの動きがぎくしゃくし、応答が重たいゲーム内容になりがちです。 ネットワークを介して入力を受け取る時間が長ければ、ゲーム展開も遅くなってしまいます。
## インプットディレイによるネットワーキング使用の場合
## 入力遅延を用いたネットワーキング
### 理論的に
### 理論上では
以下の系統図をご覧ください。統計図に理想的な0msの遅延のネットワークでつのクライエントが同期されています。 プレヤーの入力とゲームステートは青い色で、プレヤー2のは赤い色で、ネットワークレイヤが緑色で記述されています。黒い矢はシステムを経由している入力とステート遷移を表します。フレームずつは破線で分けられています。統計図はプレヤー1の視点しか見せていませんが、プレヤー2は同一のステップに従っています。
下にある図を見てください。2つのクライアントが理想的なネットワークで0ミリ秒の遅延の中、同期されている図になっています。1プレヤーの入力が青、2プレヤー側の入力は赤、ネットワーク層は緑です。黒色の矢印は入力がシステム内で送信され、ゲームステートが次へと推移する流れを示します。フレームは水平のダッシュ線で分けています。図は1プレヤー側から見た図だけになっていまが、2プレヤー側からも全く同じ手順になっています。
![](images/overview_image1.png)
ゲームエンジンに放送される前、プレヤーの入力はネットワークレイヤでプレヤー2の入力と併合されます。エンジンは現在のフレームのゲームステートをその入力を使って異動します。プレヤー2は同様、自分の入力とプレヤーの入力を併合して、組み合わせた入力をゲームエンジンに送します。ゲームはそのふうに毎フレームをプレヤーインプットによって前のフレームを加工して、続きます。プレヤーとプレヤー2は同じゲームステートから始まりまして、両方のゲームエンジンに放送した入力が一致していますので、二人のプレヤーのゲームステートは自動的にフレームずつに同期されています。
1プレヤーの入力はネットワーク層によって2プレイヤーの入力とマージし、ゲームエンジンに送信されます。エンジンはその入力を用いて現在のフレームのゲームステートを変更します。2プレヤー側も同様です。1プレヤーの入力をマージして入力をゲームエンジンに送します。プレヤーの入力した値に応じてロジックをあてはめ、過去のフレームのゲームステートを修正しながら、フレームごとにゲームが進行します。1プレヤーと2プレヤー両方が同じゲームステートで、それぞれのエンジンに送信される入力が同じなので、両プレヤーのゲームステートはフレーム同期されたままになります。
### 実践的に…
以上の理想的なネットワークのたとえで、パッケットが遅延なくネットワーク介して転送されているとする。現実はそんあに甘くはない。インフラ性質とプレヤーの間の距離によって、普通のブロードバンド接続で、パッケットを転送するのはからがかかります。あなたのゲームがFPSでしたら、その遅延はからフレームとなります。
### 実際は…
ゲームが全てのプレヤーの入力が受け取るまで続けることができませんので、ゲームは1から9フレームまでの遅延をプレヤーの入力に入道しなければならなくなります。
理想的なネットワーク例は、パケットがネットワークを介して即座に送信されるものとされていますが、実際にはそこまで理想的に動いているわけではありません。典型的なブロードバンド接続は、プレイヤー間の距離やプレヤーの住む場所にあるインフラの品質に応じ、パケットの送信が5~150ミリ秒かかります。ゲームが1秒間に60フレームで実行されるとするならば、どこでも1~9フレームの遅延が発生します。
両プレイヤーの入力を受信するまで、ゲームはフレームを処理することができないので、各プレイヤーの入力に1~9フレームの遅延、または「ラグ」を用いなくてはいけません。遅延を考慮に入れ、先ほどの図を変更してみると…
![](images/overview_image3.png)
この例でパケットを転送するにはフレーム3枚が経過する。つまり、第一フレームに送った、リモートのプレヤーの入力が、プレヤーのゲームエンジンの三フレーム後にしか到着しません。プレヤーのゲームエンジンがプレヤー2の入力を受け取る前は続くことができませんので、第一フレームを3フレーム遅延しなければなりません。従って、全部の後続のフレームもフレーム遅延されています。ネットワークレイヤーは併合した入力を,最大のプレヤーの間に交換されたパケットの片方向輸送時間で遅延しなければなりません。この遅延は多くのゲームタイプのゲームエクスペリエンスに著しい悪影響を与えることなりかねます。
この例では、パケットの送信に3フレームかかります。2プレイヤーによって遠隔から送信された入力は、1フレーム目に1プレイヤー側に届かず、3フレーム後になるまで2プレヤーの入力は1プレヤーのゲーム機に届きません。1プレヤーのゲームエンジンは入力を受信するまでゲームを進めることができないので、1フレーム目を3フレーム遅延せざるをえなくなります。続きのフレームも同様に3フレーム遅延が発生します。両プレイヤー間で送信される送信時間のために、多くのケースでネットワーク層はマージされた入力を遅延せざるを得なくなります。理想的なネットワーク環境を除いては、大半のゲームジャンルにおいてこのラグによりプレイ感に大きく影響を与えることなります。
## 入力遅延をロールバックネットワーキングで減縮する
## ロールバックネットワーキングで入力遅延を取り除く
### 投機的実行
GGPOライブラリは、インプットラグを、パケットを転送するに必要な遅延を投機的実行を使って隠すことで防ぎます。次の統計図を見ましょう。
GGPOは投機的実行を用いることで、パケット送信に必要となる遅延を隠し、入力ラグの発生を防ぎます。それでは、もう一つの図を見てみましょう。
![](images/overview_image2.png)
リモートプレヤーから入力を受け取るのを待つ代わりに、GGPOライブラリは過去の入力に基づいて、リモートプレヤーがどんな入力を入力するのを予測します。GGPOは予測した入力プレヤー1のロカルノの入力と併合して、直接に併合した入力ゲームエンジンに送ります。そうして、ゲームエンジンは次のフレームを、他のプレヤーの入力が含まれるパケットがまだ受け取れなくても、加工できます。
GGPOの予測が完璧だったら、オンラインプレイはオフラインプレイと同じになります。もちろん誰も未来を予測できませんGGPO時々プレヤーの入力を間違って予測します。上の統計図をもう一回見てください。GGPOがプレヤー2に第一フレームの瞬間に間違っている入力を転送したら、何が起こりますか?そういう時に、プレヤー2のための入力がプレヤー1のゲームとプレヤー2のゲームと異なるようになります。2つのゲームステートが同期が失って、二人のプレヤーが2つの違っている現実に作用するようになってしまいます。動機誤差はプレヤー1が正しい入力を受け取るフレームまで認識できませんが、それはもう遅すぎます
これが、GGPOの機能方法が「投機的実行」と呼ばれている理由です。プレヤーが現在のゲームのフレームのときに見えるものは正しいかもしれませんが、そうでないかもしれません。GGPOがリモートのプレヤーの入力を誤って予測する場合は、そのミスを次のフレームへ続行する前に修正しなければなりません。次の例でその方法を説明します。
遠隔のプレヤーから入力が届くのを待つ代わりに、GGPOが過去の入力をベースに他プレヤーが行いそうな入力を予測します。予測された入力と1プレヤーの入力を統合し、即座にマージされた入力ゲームエンジンに通るので、仮に他プレヤーの入力情報があるパケットが届かなくとも次のフレームへ進めることができます。
GGPOの予測が完璧であれば、オンラインで遊ぶユーザー体験はオフラインと同一のものになります。もちろん未来を予測することは誰にもできませんGGPO時々2プレヤーの入力を間違って予測します。上の図をもう一度ご覧ください。もしGGPOが1フレーム目に2プレイヤーの異なる入力を送信したとしたら1プレヤー側に表示される2プレヤーの入力は、2プレヤー側で表示されるものと異なってしまいます。両サイドのゲームは同期から外れ、プレヤーは違ったゲーム画面を見ながら相手の動きに反応することになります。同期のズレは、1プレヤー側が2プレイヤーの本来の入力が届く4フレームまで発見することができないのですが、もうそうなると手遅れになりかねません
そういうことから、GGPOの手法は「投機的実行(speculative execution)」と呼ばれます。遊んでいるプレヤーが見ているその時の情報は正しいかもしれませんが、そうでないこともあり得ます。GGPOが遠隔プレヤーの入力を誤って予測した場合、次のフレームへ進める前にエラーをただす必要があります。次の例は、どのように発生するかを説明します。
### 投機的実行のエラーをロールバックで修正する
GGPOはリモートのプレヤーの入力を過って予測した場合、ロールバックを使用して、クライアントを再同期します。ロールバックというのは、ゲームステートを巻き戻し、プレヤーの入力のより正確な情報によって、新しい結果を予測するプロセスを指します。前のセクションで我々は、予測した、リモート入力のフレームが誤っている場合では、何が起こるのかについて考えました。GGPOはエラーをどうやって修正するのかを見ましょう。
### 投機的実行エラーをロールバックで修正する
GGPOは遠隔プレイヤーがするであろう入力が間違っていたら、クライアントを再同期するためにロールバックを用います。「ロールバック」という単語は、ステートを巻き戻し、プレイヤーの入力に関する、より正しく新しい情報を元に結果を予測した過程を指します。前回のセクションでは、遠隔の入力1における予測したフレームが異なっていたらどうなるか、ということを考えました。それでは、GGPOがエラーを修正する過程を見てみましょう。
![](images/overview_image5.png)
GGPOは前のフレームのための予測の品質をリモート入力を受け取るたびにチェックします。前いいたように、GGPOはプレヤー2のはじめのフレームの入力を、プレヤー1の第四フレームまで受け取りません。プレヤー1の第四フレーム、GGPOはネットワークから受け取った入力が予測した入力一致しないことに機付きます。2つのゲームステートを再同期させるため、GGPOはゲームを間違った入力で三フレームも実行したダメージを取り消さなければなりません。そうするために、ゲームエンジンに、誤って予測した入力を送る前のステートに戻すように要求しますつまり、ゲームエンジンを前のステート「ロールバック」させるのです)。前のステートが修復された後、GGPOはゲームエンジンに修正された入力ストリームを使用して、ゲームステートをフレームずつ続行するように要請します。そのリプレーされたフレームは色で表示されます。あなたのゲームエンジンはのフレームをできるだけ早く、ユーザーが目に見える影響を与えずにリプレーする必要があります。たとえば、あなたのビデオレンダラーはこれらのフレームを画面に描画しないのがいいです。ゲームのオーディオシステムはオーディオを生成し続けすが、ロールバックが完成するまではサウンドを出力しない方がいいです。ロールバックが完成した後、サウンドサンプルは第Nフレームのサンプルの再生を開始する必要があります。Nとは現在のフレーム番号から、サンプルが生成されたフレーム番号を引いたものです
ゲームエンジンがGGPOが予測エラーに気づいた前のフレームにたどり付いたら、GGPOはロールバックモードを中止して、ゲームを通常どおり続行します。統計図の第フレームはGGPOの予測が正しい場合に起こることです。ゲームステートが正しいので、ロールバックする必要性がありません。
GGPOは遠隔の入力を受信したら、その都度前回のフレームで予測した品質をチェックします。先ほど触れたように、GGPOは4フレーム目まで2プレヤー側の入力が届きません。4フレーム目で、GGPOは以前に予測した入力とネットワークから受信した入力一致しないことに気づきます。両サイドのゲームを再同期るため、GGPOは3フレーム分の誤った入力によって発生したダメージや間違いを取り消す必要があります。誤って予測した入力を送信する前のフレームまで戻るよう、ゲームエンジンに要求します(つまり過去のステートまで「ロールバック」する)。 以前のステートを復元したら、GGPOはエンジンに正しい入力で1フレーム進めるよう要求します。このフレームは色で示しています。ゲームエンジンはのフレームをユーザーに見えない形で出来る限り素早く進める必要があります。えば、ビデオレンダラーはこのフレームを画面に描写するべきではありません。オーディオレンダラーは原則、音声を生成し続けるべきですが、ロールバックが終わるまでレンダーするべきではなく、サンプルが生成されたフレームを引いた現在のフレームであるnフレームでサンプルがスタートする必要があります。エンジンはGGPOがエラーを見つける前のフレームまで到達したら、GGPOがロールバックモードをやめ、ゲームを通常通り進めることを許可します。図の5フレームと6フレーム目はGGPOの予測が正しく行われた場合を示しています。ゲームステートが正しいので、ロールバックをする理由はありません
# コード構造
以下の統計図はGGPOセッションオブジェクトの中の主要な部分とそれらの相互関係を示しています。各コンポーネントの詳細以下に説明します。
次の図はGGPOセッションで主に動作するパーツを示したもの、また各パーツごとの関連性を示しています。各コンポーネントの詳細以下に示しています。
![](images/overview_image4.png)
## GGPOインタフェース
GGPOインタフェースはP2PとSyncTestのバックエンド実装詳細を抽象化します。ggpo_start_sessionまたはggpo_start_synctestのエントリーポイントをコールすると、適切なバックエンドが自動的に作成されます。
## GGPOインタフェース(GGPO Interface)
## P2Pバックエンド
GGPOインターフェイスはP2Pと同期テストバックエンド間の詳しい実行を抽象しています。適切なバックエンドは`ggpo_start_session``ggpo_start_synctest`エントリーポイントを呼び出した時に、自動的に生成されます。
P2Pバックエンドはプレヤー間のゲームを管理します。ggpo_start_session API呼び出しによって作成されます。含まれているヘルパークラスは大体の努力を実行します。
## ポリングオブジェクト
## P2Pバックエンド(P2P Backend)
(統計図に無い)。ポリングオブジェクトは他のコードの中のオブジェクトが使用する登録メカニズムです。このオブジェクトは待機可能のオブジェクトが準備完了になると、タイマーと通知を配信します。たとえば、UDPバックエンドはポリングオブジェクトを利用して、新しいパケットが到着する時に通知を受信します。
P2Pバックエンドはプレイヤー間でゲームを統合します。`ggpo_start_session` APIの呼び出しによって生成されます。大きな情報の処理の大半は含まれているヘルパークラスによってなされます。
## 同期Syncオブジェクト
同期オブジェクトは前のNフレームのゲームステートを管理するために利用されます。含まれる予測predictionオブジェクトが予測の過ちを通知したら、Syncバックエンドはゲームをより正確なステートに巻き戻し、予測エラーを修正するためにステートをフレームずつ続行します。
## ポルオブジェクト(Poll Object)
## 入力キューオブジェクト
(図にはありません)ポルオブジェクトはコード内で他のオブジェクトによって用いられる認証方式です。大気可能なオブジェクトが準備できたときに通知とタイマーを送信します。例としてUDPバックエンドは新たなパケットが到着したときに、通知を受信するためポルオブジェクトを使用します。
入力キューオブジェクトは全部のローカルか、リモートのプレヤーの入力を管理します。まだ受信されていない入力が要求されたら、入力キューは次の入力を予測して、予測が誤ったら、同期オブジェクトがどこまでロールバックしなければ、ならないことが分かるように、その情報を保存しておきます。求められた場合、入力キューはフレーム遅延も実行します。
## UDPプロトコルオブジェクト
## 同期オブジェクト(Sync Object)
UDPプロトコルオブジェクトは二人のプレヤー間の同期・入力交換プロトコルを処理します。このオブジェクトゲーム入力の圧縮と信頼性のあるUDPレーヤも実装します。全てのUDPプロトコルオブジェクトにはTimeSyncオブジェクトが含まれ、そのオブジェクトをプレヤーの間の時間ずれを推測するために利用しています。
同期オブジェクトゲームステートのnフレームを追跡するために用いられます。埋め込まれた予測predictionオブジェクトが予測エラーを通知された時、同期バックエンドがより正確なステートまでゲームを巻き戻し、予測エラーを正そうとシングルステップ処理を進めます。
## UDPオブジェクト
UDPオブジェクトは単純なUDPパケットのセンダー・リシーバ。違うプラットフォームへの移植を簡易にするために、UDPプロトコルから孤独されています。
## 入力キューオブジェクト(Input Queue Object)
## SyncTestバックエンド
入力キューオブジェクトはローカル、または遠隔プレイヤー向けに受信した全入力を追跡します。所持していない入力を要求された場合、入力キューは次の入力を予測し、後の情報を追跡します。そうすることで同期オブジェクトは予測が誤った場合にどこまでロールバックすればいいかわかります。リクエストがあった場合、入力キューはフレーム遅延も実行します。
(統計図に無い) SyncTestバックエンドはP2Pバックエンドと同じSyncオブジェクトを使って、実装者のアップリケーションのセーブステートとステッピング機能が決定的に実行していることを確認します。SyncTestの使い方の詳細についてはデベロップメントガイドをご参照ください。
## UDPプロトコルオブジェクト(UDP Protocol Object)
UDPプロトコルオブジェクトは両プレイヤー間の同期と入力エクスチェンジプロトコルを扱います。また、ゲーム入力圧縮と信頼できるUDP層の実行も行います。各UDPプロトコルオブジェクトには同期オブジェクトが含まれ、そのオブジェクトをプレヤーの間の時間ずれを推測するために利用しています。
## UDPオブジェクト(UDP Object)
UDPオブジェクトは単純なUDPパケットセンダー・リレシーバーです。違うプラットフォームへの移植を簡易にするために、UDPプロトコルから分離します。
## 同期テストバックエンド(Sync Test Backend)
(図にはありません)同期テストバックエンドは、P2Pバックエンドがアプリのセーブステートと決定的に機能上実行していることを確認するときに同じ同期オブジェクトを使用します。同期テストの使用に関する詳しい情報は、開発者向けガイドをご覧ください。