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:
@@ -1,90 +1,101 @@
|
||||
# GGPOとは何か?
|
||||
# GGPOとは?
|
||||
|
||||
2009年に作成されたGGPOネットワーキングSDKは、ピアツーピアゲームでのロールバックネットワーキングの使用を開拓しました。 非常に正確な入力とフレームの完全な実行を必要とする速いペースの単収縮スタイルのゲームでネットワーク遅延を隠すために特別に設計されています。
|
||||
2009年に開発されたGGPOネットワーキングSDKは、ピアトゥピアゲームにおけるロールバックネットワーキング実用化の先駆けとなったシステムです。正確な入力や、フレームごとの完璧な処理を必要とし、ゲーム展開が速くかつ配信に適したゲームにおいて、ネットワーク遅延を目立たなくさせることに重点を置いて開発されました。
|
||||
|
||||
従来の手法では、プレーヤーの入力に遅延を追加することでネットワークの送信時間を考慮し、結果としてゲームの動きが鈍くなります。 ロールバックネットワーキングは、入力予測と投機的実行を使用して、プレーヤーの入力を直ちにゲームに送信し、ゼロ遅延ネットワークの錯覚を与えます。ロールバックネットコードを用いて、プレイヤーがオフラインでプレイすることで蓄積した筋肉のメモリ、タイミング、リアクション、およびをビジュアルキューとオーディオキューオンラインでも直接に利用できます。 GGPOネットワーキングSDKは、ロールバックネットワーキングをできるだけ簡単に、新規および既存のゲームに組み込むことができるように設計されています。
|
||||
従来の技術はプレイヤーの入力に遅延を織り込んで通信を行っており、その結果反応が遅く、ラグを感じるプレイ感になっていました。ロールバックネットワーキングはプレイヤーの入力を即座に送信するため、入力予測と投機的実行を行うことにより、遅延ゼロの回線環境をもたらせるのです。ロールバックがあれば、タイミングや相手の動きや効果音に対しての反応、指が覚えている入力、これらオフラインで行えた内容が、そのままオンラインでも行えます。GGPOネットワーキングSDKは、ロールバックネットワーキングを新作や発売されているゲームに極力簡単に組み込めるよう作られています。
|
||||
|
||||
|
||||
# 仕組みは?
|
||||
# どう動作する?
|
||||
|
||||
ロールバックネットワーキングは、完全に決定的なピアツーピアエンジンに統合されるように設計されています。完全な決定論により、単に同じ入力をフィードするだけで、すべてのプレイヤーコンピューターで同じ方法でゲームがプレイされることが保証されます。これを実現する1つの方法は、ネットワーク経由ですべてのプレーヤーの入力を交換し、すべてのプレーヤーがピアからすべての入力を受け取ったときにのみゲームプレイロジックのフレームを実行することです。そうすると、多くの場合、結果としてゲームプレイの反応が遅く、応答が遅くなります。ネットワークを介して入力を取得するのに時間がかかるほど、ゲームは遅くなります。
|
||||
ロールバックネットワーキングは決定的ピアトゥピアエンジンに統合できるよう設計されています。 完全に決定的なエンジンなら、同じ入力をした場合にゲームは必ず同じ内容のプログラム再生をします。 その内容を実現する一つの方法としては、ネットワーク上に全プレイヤーと入力をやりとりをする方法があげられますが、これは全プレイヤーがピアから全入力を受け取った時にゲームプレイロジックが1フレームだけ実行する形になります。 この方法ではゲーム内でキャラの動きがぎくしゃくし、応答が重たいゲーム内容になりがちです。 ネットワークを介して入力を受け取る時間が長ければ、ゲーム展開も遅くなってしまいます。
|
||||
|
||||
|
||||
## インプットディレイによるネットワーキング使用の場合
|
||||
## 入力遅延を用いたネットワーキング
|
||||
|
||||
### 理論的に…
|
||||
### 理論上では…
|
||||
|
||||
以下の系統図をご覧ください。統計図に理想的な0msの遅延のネットワークで2つのクライエントが同期されています。 プレヤー1の入力とゲームステートは青い色で、プレヤー2のは赤い色で、ネットワークレイヤが緑色で記述されています。黒い矢はシステムを経由している入力とステート遷移を表します。フレームずつは破線で分けられています。統計図はプレヤー1の視点しか見せていませんが、プレヤー2は同一のステップに従っています。
|
||||
下にある図を見てください。2つのクライアントが理想的なネットワークで0ミリ秒の遅延の中、同期されている図になっています。1プレイヤー側の入力が青、2プレイヤー側の入力は赤、ネットワーク層は緑です。黒色の矢印は入力がシステム内で送信され、ゲームステートが次へと推移する流れを示します。各フレームは水平のダッシュ線で分けています。図は1プレイヤー側から見た図だけになっていますが、2プレイヤー側からも全く同じ手順になっています。
|
||||
|
||||

|
||||
|
||||
ゲームエンジンに放送される前、プレヤー1の入力はネットワークレイヤでプレヤー2の入力と併合されます。エンジンは現在のフレームのゲームステートをその入力を使って異動します。プレヤー2は同様、自分の入力とプレヤー1の入力を併合して、組み合わせた入力をゲームエンジンに放送します。ゲームはそのふうに毎フレームをプレヤーインプットによって前のフレームを加工して、続きます。プレヤー1とプレヤー2は同じゲームステートから始まりまして、両方のゲームエンジンに放送した入力が一致していますので、二人のプレヤーのゲームステートは自動的にフレームずつに同期化されています。
|
||||
1プレイヤーの入力は、ネットワーク層によって2プレイヤーの入力とマージし、ゲームエンジンに送信されます。エンジンはその入力を用いて現在のフレームのゲームステートを変更します。2プレイヤー側も同様です。1プレイヤーの入力をマージして入力をゲームエンジンに送信します。プレイヤーの入力した値に応じてロジックをあてはめ、過去のフレームのゲームステートを修正しながら、フレームごとにゲームが進行します。1プレイヤーと2プレイヤー両方が同じゲームステートで、それぞれのエンジンに送信される入力が同じなので、両プレイヤーのゲームステートは毎フレーム同期されたままになります。
|
||||
|
||||
### 実践的に…
|
||||
|
||||
以上の理想的なネットワークのたとえで、パッケットが遅延なくネットワーク介して転送されているとする。現実はそんあに甘くはない。インフラ性質とプレヤーの間の距離によって、普通のブロードバンド接続で、パッケットを転送するのは5msから150msがかかります。あなたのゲームが60FPSでしたら、その遅延は1から9フレームとなります。
|
||||
### 実際は…
|
||||
|
||||
ゲームが全てのプレヤーの入力が受け取るまで続けることができませんので、ゲームは1から9フレームまでの遅延をプレヤーの入力に入道しなければならなくなります。
|
||||
理想的なネットワーク例は、パケットがネットワークを介して即座に送信されるものとされていますが、実際にはそこまで理想的に動いているわけではありません。典型的なブロードバンド接続は、プレイヤー間の距離やプレイヤーの住む場所にあるインフラの品質に応じ、パケットの送信が5~150ミリ秒かかります。ゲームが1秒間に60フレームで実行されるとするならば、どこでも1~9フレームの遅延が発生します。
|
||||
|
||||
両プレイヤーの入力を受信するまで、ゲームはフレームを処理することができないので、各プレイヤーの入力に1~9フレームの遅延、または「ラグ」を用いなくてはいけません。遅延を考慮に入れ、先ほどの図を変更してみると…
|
||||
|
||||

|
||||
|
||||
この例でパケットを転送するにはフレーム3枚が経過する。つまり、第一フレームに送った、リモートのプレヤー2の入力が、プレヤー1のゲームエンジンの三フレーム後にしか到着しません。プレヤー1のゲームエンジンがプレヤー2の入力を受け取る前は続くことができませんので、第一フレームを3フレームで遅延しなければなりません。従って、全部の後続のフレームも3フレームで遅延されています。ネットワークレイヤーは併合した入力を,最大のプレヤーの間に交換されたパケットの片方向輸送時間で遅延しなければなりません。この遅延は多くのゲームタイプのゲームエクスペリエンスに著しい悪影響を与えることになりかねます。
|
||||
この例では、パケットの送信に3フレームかかります。2プレイヤーによって遠隔から送信された入力は、1フレーム目に1プレイヤー側に届かず、3フレーム後になるまで2プレイヤーの入力は1プレイヤー側のゲーム機に届きません。1プレイヤー側のゲームエンジンは入力を受信するまでゲームを進めることができないので、1フレーム目を3フレーム分遅延せざるをえなくなります。続きのフレームも同様に3フレーム分遅延が発生します。両プレイヤー間で送信される送信時間のために、多くのケースでネットワーク層はマージされた入力を遅延せざるを得なくなります。理想的なネットワーク環境を除いては、大半のゲームジャンルにおいてこのラグによりプレイ感に大きく影響を与えることとなります。
|
||||
|
||||
## 入力遅延をロールバックネットワーキングで減縮する
|
||||
|
||||
## ロールバックネットワーキングで入力遅延を取り除く
|
||||
|
||||
### 投機的実行
|
||||
|
||||
GGPOライブラリは、インプットラグを、パケットを転送するに必要な遅延を投機的実行を使って隠すことで防ぎます。次の統計図を見ましょう。
|
||||
GGPOは投機的実行を用いることで、パケット送信に必要となる遅延を隠し、入力ラグの発生を防ぎます。それでは、もう一つの図を見てみましょう。
|
||||
|
||||

|
||||
|
||||
リモートプレヤーから入力を受け取るのを待つ代わりに、GGPOライブラリは過去の入力に基づいて、リモートプレヤーがどんな入力を入力するのを予測します。GGPOは予測した入力をプレヤー1のロカルノの入力と併合して、直接に併合した入力をゲームエンジンに送ります。そうして、ゲームエンジンは次のフレームを、他のプレヤーの入力が含まれるパケットがまだ受け取れなくても、加工できます。
|
||||
GGPOの予測が完璧だったら、オンラインプレイはオフラインプレイと同じになります。もちろん誰も未来を予測できません。GGPOは時々、プレヤー2の入力を間違って予測します。上の統計図をもう一回見てください。GGPOがプレヤー2に第一フレームの瞬間に間違っている入力を転送したら、何が起こりますか?そういう時に、プレヤー2のための入力がプレヤー1のゲームとプレヤー2のゲームと異なるようになります。2つのゲームステートが同期が失って、二人のプレヤーが2つの違っている現実に作用するようになってしまいます。動機誤差はプレヤー1が正しい入力を受け取るフレーム4まで認識できませんが、それはもう遅すぎます。
|
||||
これが、GGPOの機能方法が「投機的実行」と呼ばれている理由です。プレヤーが現在のゲームのフレームのときに見えるものは正しいかもしれませんが、そうでないかもしれません。GGPOがリモートのプレヤーの入力を誤って予測する場合は、そのミスを次のフレームへ続行する前に修正しなければなりません。次の例でその方法を説明します。
|
||||
遠隔のプレイヤーから入力が届くのを待つ代わりに、GGPOが過去の入力をベースに他プレイヤーが行いそうな入力を予測します。予測された入力と1プレイヤーの入力を統合し、即座にマージされた入力がゲームエンジンに通るので、仮に他プレイヤーの入力情報があるパケットが届かなくとも次のフレームへ進めることができます。
|
||||
GGPOの予測が完璧であれば、オンラインで遊ぶユーザー体験はオフラインと同一のものになります。もちろん、未来を予測することは誰にもできません!GGPOも時々2プレイヤーの入力を間違って予測します。上の図をもう一度ご覧ください。もしGGPOが1フレーム目に2プレイヤーの異なる入力を送信したとしたら?1プレイヤー側に表示される2プレイヤーの入力は、2プレイヤー側で表示されるものと異なってしまいます。両サイドのゲームは同期から外れ、プレイヤーは違ったゲーム画面を見ながら相手の動きに反応することになります。同期のズレは、1プレイヤー側が2プレイヤーの本来の入力が届く4フレーム目まで発見することができないのですが、もうそうなると手遅れになりかねません。
|
||||
そういうことから、GGPOの手法は「投機的実行(speculative execution)」と呼ばれます。遊んでいるプレイヤーが見ているその時の情報は正しいかもしれませんが、そうでないこともあり得ます。GGPOが遠隔プレイヤーの入力を誤って予測した場合、次のフレームへ進める前にエラーをただす必要があります。次の例は、どのように発生するかを説明します。
|
||||
|
||||
### 投機的実行のエラーをロールバックで修正する
|
||||
|
||||
GGPOはリモートのプレヤーの入力を過って予測した場合、ロールバックを使用して、クライアントを再同期します。ロールバックというのは、ゲームステートを巻き戻し、プレヤーの入力のより正確な情報によって、新しい結果を予測するプロセスを指します。前のセクションで我々は、予測した、リモート入力1のフレームが誤っている場合では、何が起こるのかについて考えました。GGPOはエラーをどうやって修正するのかを見ましょう。
|
||||
### 投機的実行エラーをロールバックで修正する
|
||||
|
||||
GGPOは遠隔プレイヤーがするであろう入力が間違っていたら、クライアントを再同期するためにロールバックを用います。「ロールバック」という単語は、ステートを巻き戻し、プレイヤーの入力に関する、より正しく新しい情報を元に結果を予測した過程を指します。前回のセクションでは、遠隔の入力1における予測したフレームが異なっていたらどうなるか、ということを考えました。それでは、GGPOがエラーを修正する過程を見てみましょう。
|
||||
|
||||

|
||||
|
||||
GGPOは前のフレームのための予測の品質をリモート入力を受け取るたびにチェックします。前いいたように、GGPOはプレヤー2のはじめのフレームの入力を、プレヤー1の第四フレームまで受け取りません。プレヤー1の第四フレームに、GGPOはネットワークから受け取った入力が予測した入力と一致しないことに機付きます。2つのゲームステートを再同期させるために、GGPOはゲームを間違った入力で三フレームも実行したダメージを取り消さなければなりません。そうするために、ゲームエンジンに、誤って予測した入力を送る前のステートに戻すように要求します(つまり、ゲームエンジンを前のステートへ「ロールバック」させるのです)。前のステートが修復された後、GGPOはゲームエンジンに修正された入力ストリームを使用して、ゲームステートをフレームずつ続行するように要請します。そのリプレーされたフレームは水色で表示されます。あなたのゲームエンジンはそのフレームをできるだけ早く、ユーザーが目に見える影響を与えずにリプレーする必要があります。たとえば、あなたのビデオレンダラーはこれらのフレームを画面に描画しないのがいいです。ゲームのオーディオシステムはオーディオを生成し続けますが、ロールバックが完成するまではサウンドを出力しない方がいいです。ロールバックが完成した後、サウンドサンプルは第Nフレームのサンプルの再生を開始する必要があります。Nとは現在のフレーム番号から、サンプルが生成されたフレーム番号を引いたものです。
|
||||
ゲームエンジンがGGPOが予測エラーに気づいた前のフレームにたどり付いたら、GGPOはロールバックモードを中止して、ゲームを通常どおり続行します。統計図の第5と6フレームはGGPOの予測が正しい場合に起こることです。ゲームステートが正しいので、ロールバックする必要性がありません。
|
||||
GGPOは遠隔の入力を受信したら、その都度前回のフレームで予測した品質をチェックします。先ほど触れたように、GGPOは4フレーム目まで2プレイヤー側の入力が届きません。4フレーム目で、GGPOは以前に予測した入力とネットワークから受信した入力が一致しないことに気づきます。両サイドのゲームを再同期するため、GGPOは3フレーム分の誤った入力によって発生したダメージや間違いを取り消す必要があります。誤って予測した入力を送信する前のフレームまで戻るよう、ゲームエンジンに要求します(つまり過去のステートまで「ロールバック」する)。 以前のステートを復元したら、GGPOはエンジンに正しい入力で1フレーム進めるよう要求します。このフレームは空色で示しています。ゲームエンジンはこのフレームをユーザーに見えない形で出来る限り素早く進める必要があります。例えば、ビデオレンダラーはこのフレームを画面に描写するべきではありません。オーディオレンダラーは原則、音声を生成し続けるべきですが、ロールバックが終わるまでレンダーするべきではなく、サンプルが生成されたフレームを引いた現在のフレームであるnフレームでサンプルがスタートする必要があります。エンジンはGGPOがエラーを見つける前のフレームまで到達したら、GGPOがロールバックモードをやめ、ゲームを通常通り進めることを許可します。図の5フレームと6フレーム目はGGPOの予測が正しく行われた場合を示しています。ゲームステートが正しいので、ロールバックをする理由はありません。
|
||||
|
||||
|
||||
# コード構造
|
||||
|
||||
以下の統計図はGGPOセッションオブジェクトの中の主要な部分とそれらの相互関係を示しています。各コンポーネントの詳細を以下に説明します。
|
||||
次の図はGGPOセッションで主に動作するパーツを示したもの、また各パーツごとの関連性を示しています。各コンポーネントの詳細は以下に示しています。
|
||||
|
||||

|
||||
|
||||
## 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バックエンドがアプリのセーブステートと決定的に機能上実行していることを確認するときに同じ同期オブジェクトを使用します。同期テストの使用に関する詳しい情報は、開発者向けガイドをご覧ください。
|
||||
|
||||
Reference in New Issue
Block a user