Ja/Source Multiplayer Networking: Difference between revisions

From Valve Developer Community
< Ja
Jump to navigation Jump to search
No edit summary
 
m (fix)
Line 1: Line 1:
[[Category:Japanese]]
[[Category:Japanese]]
Source Engine�?��?�マル�?プレイヤー�?ットワーキング
Source Engineでのマルチプレイヤーネットワーキング


=概?=
[[Source Engine]]?マル?プレイヤーゲーム??クライアント/サー??ットワークアーキテク?ャを使用?????。通常サー??専用?ホスト????ゲームを実行??ワールドシミュレーション?ゲームルール?プレイヤーインプット処??関??信頼???るも?(authoritative?訳注:ゲームロジック処?を集中??行???サー?)??り??。クライアント?ゲームサー??接続??プレイヤー?コンピュータ??。クライアント?サー???互?????データパケットを高頻度(通常1秒?20?ら30パケット)??り????。クライアント?サー??ら?在?ワールド?状態を???り???れら?更新情報をも??ビデオ?音声?アウトプットを作り出???。クライアント????入力デ?イス(キーボード?マウス?マイク??)?ら?データをサンプル???れら?情報を?ら?る処?????サー???り返???。クライアント?ゲームサー????通信を行??クライアント?士?通信(peer-to-peer通信?よ??)を行???ん。シングルプレイヤーゲーム?????マル?プレイヤーゲーム???????パケット?基???通信?起因?る新???多様??題??り組む必???り??。


�?ットワーク帯域�?��?��?り�?��?�る�?��?��?ワールド�?��?�一�?�一�?��?�変更全�?��?�対�?��?��?サー�?�?�全�?��?�クライアント�?��?��?�更新パケットを�?り出�?��?��?��?��?��?��?��?�?�能�?��?�。�??�?�代�?り�?��? サー�?�?��?�在�?�ワールド�?�状態を一定�?�間隔�?�スナップショット�?��?��?�形�?��?��?�?�れら�?�スナップショットをクライアント�?�ブロードキャスト�?��?��?�。�?ットワークパケット�?�クライアント�?サー�?間を移動�?�る�?��?�時間�?��?��?�り�?��?�(�?�れ�?�ping時間�?��?�)。�?�れ�?�より�?クライアント時間�?�サー�?時間より常�?�少�?��?�れ�?��?�る�?��?��?��?��?��?��?�り�?��?�。�?�ら�?��?クライアント�?�ら�?�インプットパケット�?�届�??�?��?�も�?�延�?��?�り�?サー�?�?�常�?��?�延�?��?�ユーザコマンドを処�?��?��?��?�る�?��?��?��?�り�?��?�。追加�?��?��?他�?��?ックグラウンド�?�トラフィックやクライアント�?�フレームレート�?��?�影響�?�れ�?��?�??れ�?�れ�?�クライアント�?��?ットワーク�?�れ�?�様々�?��?�?��?�も時間�?��?�も�?�変化�?��?��?�。�?��?��?��?��?�サー�?�?�クライアント�?��?�時間�?��?��?��?�論�?�的�?��?題を引�??起�?��?��?�?ットワークレイテンシ(�?�延)�?�増加�?�る�?�共�?�悪化�?��?��?�。早�?�ペース�?�アクションゲーム�?��?��?��?��?��?�?��?��?�数ミリ秒�?��?�れ�?��?��?��?�もラグ�?��?�るゲームプレイ感覚を引�??起�?��?��?他�?�プレイヤーを撃�?��?�り�?動�??オブジェクト�?�インタラクションを行�?��?��?��?�難�?��??�?�り�?��?�。帯域�?�制�?�?��?ットワークレイテンシ�?�加�?��?情報�?��?ットワークパケットロス�?�失�?れる�?��?�も�?�り�?��?�。
=概要=
[[Source Engine]]のマルチプレイヤーゲームではクライアント/サーバネットワークアーキテクチャを使用しています。通常サーバは専用のホストとなってゲームを実行し、ワールドシミュレーション、ゲームルール、プレイヤーインプット処理に関して信頼できるもの(authoritative、訳注:ゲームロジック処理を集中して行うのはサーバ)になります。クライアントはゲームサーバに接続したプレイヤーのコンピュータです。クライアントとサーバはお互いに小さなデータパケットを高頻度(通常1秒に20から30パケット)で送りあいます。クライアントはサーバから現在のワールドの状態を受け取り、それらの更新情報をもとにビデオと音声のアウトプットを作り出します。クライアントはまた、入力デバイス(キーボード、マウス、マイクなど)からのデータをサンプルし、これらの情報をさらなる処理のためにサーバに送り返します。クライアントはゲームサーバとのみ通信を行い、クライアント同士の通信(peer-to-peer通信のような)を行いません。シングルプレイヤーゲームとは違い、マルチプレイヤーゲームにおいてはこのパケットに基づいた通信に起因する新しく多様な問題に取り組む必要があります。
 
ネットワーク帯域には限りがあるので、ワールドでの一つ一つの変更全てに対して、サーバが全てのクライアント向けに更新パケットを送り出すということは不可能です。その代わりに、 サーバは現在のワールドの状態を一定の間隔でスナップショットという形にし、これらのスナップショットをクライアントにブロードキャストします。ネットワークパケットがクライアント、サーバ間を移動するには時間がかかります(これがping時間です)。これにより、クライアント時間はサーバ時間より常に少し遅れているということになります。さらに、クライアントからのインプットパケットが届くのにも遅延があり、サーバは常に遅延したユーザコマンドを処理していることになります。追加して、他のバックグラウンドのトラフィックやクライアントのフレームレートのに影響されて、それぞれのクライアントのネットワーク遅れは様々で、しかも時間とともに変化します。こうしたのサーバとクライアントでの時間の違いは論理的な問題を引き起こし、ネットワークレイテンシ(遅延)が増加すると共に悪化します。早いペースのアクションゲームにおいては、たとえ数ミリ秒の遅れであってもラグのあるゲームプレイ感覚を引き起こし、他のプレイヤーを撃ったり、動くオブジェクトとインタラクションを行うことが難しくなります。帯域の制限とネットワークレイテンシに加え、情報がネットワークパケットロスで失われることもあります。


<center>[[Image:Networking1.gif]]</center>
<center>[[Image:Networking1.gif]]</center>


�?ットワーク通信�?�よ�?��?�発生�?��?��?�れら�?��?題全�?��?�対処�?�る�?��?�?��?Source Engine�?�複数�?�テクニックを使�?��?��?�?題を解決�?も�?��??�?�少�?��??�?�もプレイヤー�?��?題�?�気�?��??�?��??�??�?�るよ�?��?��?��?��?��?��?�。テクニック�?��?��?データ圧縮�?補間(interpolation)�?予測(prediction)�?�??�?��?�ラグ補償(compensation)�?��?�り�?��?�。�?�れら�?�テクニック�?�密接�?�組�?��?��?�?�れ�?��?�る�?��?��?1�?��?�システム�?�変更�?�他�?�システム�?�も影響�?�る�?�能性�?��?�り�?��?�。�?��?�ドキュメント�?��?��?�れら�?�システム�?�基本機能�?��?�??�?�連�?��?��?��?��?�説明�?��?��?�。
ネットワーク通信によって発生したこれらの問題全てに対処するために、Source Engineは複数のテクニックを使って、問題を解決、もしくは少なくともプレイヤーが問題に気づきにくくするようにしています。テクニックには、データ圧縮、補間(interpolation)、予測(prediction)、そしてラグ補償(compensation)があります。これらのテクニックが密接に組み合わされているので、1つのシステムの変更は他のシステムにも影響する可能性があります。このドキュメントではこれらのシステムの基本機能と、その連携について説明します。




=�?ットワーク�?�基本=
=ネットワークの基本=
サー�?�?�tick�?��?��?��?�連続的�?�時間ステップを使�?��?�ゲーム�?�シミュレーション計算を行�?��?��?�。�?期設定�?��?�1秒�?�66�?�tick�?�シミュレーション�?�れ�?��?��?��?MOD�?��?�独自�?�tickrate(1秒間�?�実行�?�るtick数)を指定�?�る�?��?��?��?��??�?��?�。例�?��?�[[Counter-Strike: Source]]�?��?�サー�?CPU負�?�を減ら�?��?��?�?��?�れより低�?�33 tick/秒�?�設定�?��?��?��?��?��?��?�。�??れ�?�れ�?�tick�?��?��?��?��?サー�?�?�入力�?�れ�?�ユーザコマンドを処�?��?��?物�?�シミュレーションステップを実行�?��?ゲームルールを�?ェック�?��?全�?��?�オブジェクト状態を更新�?��?��?�。tick�?�シミュレーション�?�終�?�?��?�ら�?サー�?�?�ワールド更新�?�必�?�?�クライアント�?��?�る�?�を決定�?��?必�?�?�応�?��?��?�在�?�ワールド状態�?�スナップショットを作�?�?��?��?�。tickrate�?�高�??�?�る�?�シミュレーション精度�?�高�?�り�?��?��?��?より多�??�?�CPUパワー�?�??�?��?�サー�?�?クライアント両方�?�使用�?�能帯域�?�必�?�?��?�り�?��?�。サー�?管�?�者�?��?期設定�?�tickrateを<code>-tickrate</code>コマンドラインパラメータ�?�上書�??�?�る�?��?��?��?��??�?��?��?��?�?��?��?��?�tickrate�?�変更�?�mod�?�デザイン�?�れ�?�よ�?��?�動作�?��?��?��?�能性�?��?�る�?��?推奨�?�れ�?��?�ん。
サーバはtickという非連続的な時間ステップを使ってゲームのシミュレーション計算を行います。初期設定では1秒に66のtickがシミュレーションされますが、MODでは独自のtickrate(1秒間に実行するtick数)を指定することができます。例えば[[Counter-Strike:_Source" title="Counter-Strike: Source">Counter-Strike: Source]]ではサーバCPU負荷を減らすためにこれより低い33 tick/秒の設定になっています。それぞれのtickにおいて、サーバは入力されたユーザコマンドを処理し、物理シミュレーションステップを実行し、ゲームルールをチェックし、全てのオブジェクト状態を更新します。tickのシミュレーションが終わったら、サーバはワールド更新が必要なクライアントがいるかを決定し、必要に応じて現在のワールド状態のスナップショットを作成します。tickrateが高くなるとシミュレーション精度が高まりますが、より多くのCPUパワー、そしてサーバ、クライアント両方の使用可能帯域が必要になります。サーバ管理者は初期設定のtickrateを<code >-tickrate</code >コマンドラインパラメータで上書きすることができますが、こうしたtickrateの変更はmodがデザインされたように動作しない可能性があるため推奨されません。


クライアント�?�使用�?�能�?�帯域�?�通常�?��??�?られ�?�も�?��?��?�。最悪�?�場�?��?��?��?��?��?��?プレイヤー�?�モデムを使用�?��?��?��?��?5-7KB/秒以上�?��?��?�れ�?��?��?��?��?��?��?�も�?�り�?��?��?�。も�?�サー�?�?��??�?��?��?�プレイヤー�?�より大�??�?�データ�?�?�更新情報を�?�?�?��?��?��?�場�?��?パケットロス�?��?��?�る�?��?��?��?��??�?��?��?��?�ょ�?�。�??�?��?��?�?クライアント�?�サー�?�?�対�?��?�自身�?��?�信帯域能力をコンソール変数<code>rate</code> (byte/秒)を設定�?��?��?�?�る必�?�?��?�り�?��?�。�?�れ�?�クライアント�?��?�最も�?�?�?��?ットワーク変数�?��?最�?��?�ゲームプレイ体験を得る�?��?�?��?��?�れを正�?��??設定�?�る必�?�?��?�り�?��?�。クライアント�?�<code>cl_updaterate</code> (�?期設定20)を変更�?�る�?��?��?�スナップショット頻度�?��?求をサー�?�?�出�?��?��?��?��?��??�?��?��?��?サー�?�?�シミュレーション�?�tick以上やクライアント�?��?求�?��?�<code>rate</code>以上�?�スナップショットを�?る�?��?��?��?��?��?�ん。サー�?管�?�者�?�クライアント�?��?求�?�るデータ�?を<code>sv_minrate</code>�?�<code>sv_maxrate</code>(�?��?�らも�?イト/秒)�?�制�?�?�る�?��?��?��?��??�?��?�。スナップショット頻度�?�<code>sv_minupdaterate</code>�?�<code>sv_maxupdaterate</code> (�?��?�らもスナップショット数/秒)�?�制�?�?�る�?��?��?��?��??�?��?�。
クライアントが使用可能な帯域は通常ごく限られたものです。最悪の場合においては、プレイヤーがモデムを使用していて、5-7KB/秒以上受け取れないということもありえます。もしサーバがそうしたプレイヤーにより大きなデータ量で更新情報を送ろうとした場合、パケットロスは避けることができないでしょう。そのため、クライアントはサーバに対して自身の受信帯域能力をコンソール変数<code >rate</code > (byte/秒)を設定して伝える必要があります。これがクライアントでの最も重要なネットワーク変数で、最適なゲームプレイ体験を得るためにはこれを正しく設定する必要があります。クライアントは<code >cl_updaterate</code > (初期設定20)を変更することでスナップショット頻度の要求をサーバに出すことができますが、サーバはシミュレーションのtick以上やクライアントの要求した<code >rate</code >以上のスナップショットを送ることはしません。サーバ管理者はクライアントが要求するデータ量を<code >sv_minrate</code ><code >sv_maxrate</code >(どちらもバイト/秒)で制限することができます。スナップショット頻度は<code >sv_minupdaterate</code ><code >sv_maxupdaterate</code > (どちらもスナップショット数/秒)で制限することができます。


クライアント�?�サー�?�?�tick頻度�?��?��?�tick頻度�?�入力デ�?イス�?�サンプリングを行�?��?''ユーザコマンド''を作�?�?��?��?�。ユーザコマンド�?�基本的�?��?��??�?��?��??�?�キーボード�?�マウス状態�?�スナップショット�?��?�。�?��?��?��?��?��?��?��??れ�?�れ�?�ユーザコマンド�?��?��?��?�新�?��?�パケットを�?信�?�る�?��?��?��?��??�?クライアント�?�決�?��?��?�頻度(通常1秒�?�30回)�?�コマンドパケットを�?信�?��?��?�。�?��?�り1�?��?�パケット�?�中�?�2�?�以上�?�ユーザコマンド�?��?信�?�れる�?��?�も�?�り�?��?�。クライアント�?��?��?��?�<code>cl_cmdrate</code>を変更�?�る�?��?��?�コマンド�?信頻度を増加�?��?�る�?��?��?��?��??�?��?�。�?�れ�?�より�??応性�?�上�?�り�?��?��?��?より多�??�?��?信帯域�?�必�?�?��?�り�?��?�。
クライアントはサーバのtick頻度と同じtick頻度で入力デバイスのサンプリングを行い、<i>ユーザコマンド</i>を作成します。ユーザコマンドは基本的にはそのときのキーボードとマウス状態のスナップショットです。しかしここではそれぞれのユーザコマンドについて新しいパケットを送信するのではなく、クライアントは決まった頻度(通常1秒に30回)でコマンドパケットを送信します。つまり1つのパケットの中で2つ以上のユーザコマンドが送信されることもあります。クライアントにおいて<code >cl_cmdrate</code >を変更することでコマンド送信頻度を増加させることができます。これにより反応性が上がりますが、より多くの送信帯域が必要になります。


ゲームデータ�?��?ットワーク負�?�を減ら�?��?��?�?�''差分圧縮(delta compression)''を使�?��?�圧縮�?�れ�?��?�。�?��?�りサー�?�?�毎回完全�?�ワールドスナップショットを�?信�?�る�?��?��?��?��??�?直�?�?�確�?�?�れ�?�スナップショット�?�ら変化�?��?�部分(差分スナップショット)�?��?�を�?信�?��?��?�。クライアント�?�サー�?�?�間�?��?信�?�れる�??れ�?�れ�?�パケット�?��?��?データ�?��?れを把�?��?�る�?��?�?�確�?番�?��?��?��?�られ�?��?��?��?�。通常完全�?�(差分�?��?��?��?�)スナップショット�?�ゲーム開始時や�?クライアント�?�数秒�?�間�?大�?�パケットロス�?�苦�?�ん�?�時�?��?��?��?信�?�れ�?��?�。クライアント�?�<code>cl_fullupdate</code>コマンド�?�手動�?�完全スナップショット�?�リクエストを出�?��?��?��?��?��??�?��?�。
ゲームデータはネットワーク負荷を減らすために<i>差分圧縮(delta compression)</i>を使って圧縮されます。つまりサーバは毎回完全なワールドスナップショットを送信するのではなく、直前の確認されたスナップショットから変化した部分(差分スナップショット)だけを送信します。クライアントとサーバの間に送信されるそれぞれのパケットには、データの流れを把握するために確認番号がつけられています。通常完全な(差分ではない)スナップショットはゲーム開始時や、クライアントが数秒の間重大なパケットロスに苦しんだ時だけに送信されます。クライアントは<code >cl_fullupdate</code >コマンドで手動で完全スナップショットのリクエストを出すことができます。


�??応性�?言�?��?��?�る�?�ユーザ�?�入力を�?��?��?�らゲームワールド�?��?�ビジュアルフィード�?ック�?��?�る�?��?��?�時間�?�?�様々�?��?因�?�よ�?��?�決�?�り�?��?�。サー�?/クライアント�?�CPU負�?��?シミュレーションtickrate�?データ転�?�?�?スナップショット更新設定�?��?�も�??れら�?��?因�?��?��?�れ�?��?��?��?大部分�?�パケット�?��?ットワークを移動�?�る�?��?��?��?�る時間�?�よるも�?��?��?�。クライアント�?�ユーザコマンドを�?信�?��?サー�?�?�応答�?��?クライアント�?��??�?�サー�?�?�応答を�?��?��?�る�?��?��?�時間�?�''レイテンシ''''ping''(も�?��??�?�ラウンドトリップタイム)�?�呼�?�れ�?��?�。マル�?プレイヤーオンラインゲームを�?��?�場�?��?低レイテンシ�?��?��?�り有利�?��?�り�?��?�。予測(prediction)�?�??�?��?�ラグ補償(compensation)�?��?��?��?�テクニック�?��?��?�有利�?�を最�?�?�?��?��?��?�?��?�接続�?�プレイヤーも公正�?�ゲーム�?��?��??るよ�?��?��?�よ�?��?��?�るも�?��?��?�。必�?�?�帯域�?�CPUパワー�?��?�れ�?��?ットワーク設定を調整�?�る�?��?��?�よりよ�?�ゲーム体験を得る助�?��?��?�り�?��?�。�?��?��?�?�切�?�変更�?�実際�?�利益よりマイナス�?�副作用を起�?��?��?��?��?�?期設定を使�?��?��?�を推奨�?��?��?�。
反応性、言い換えるとユーザが入力をしてからゲームワールドでのビジュアルフィードバックがあるまでの時間、は様々な要因によって決まります。サーバ/クライアントのCPU負荷、シミュレーションtickrate、データ転送量、スナップショット更新設定などもそれらの要因に含まれますが、大部分はパケットがネットワークを移動するのにかかる時間によるものです。クライアントがユーザコマンドを送信し、サーバが応答し、クライアントがそのサーバの応答を受け取るまでの時間は<i>レイテンシ</i><i>ping</i>(もしくはラウンドトリップタイム)と呼ばれます。マルチプレイヤーオンラインゲームを遊ぶ場合、低レイテンシはかなり有利になります。予測(prediction)、そしてラグ補償(compensation)といったテクニックはこの有利さを最小限にして、遅い接続のプレイヤーも公正なゲームができるようにしようとするものです。必要な帯域とCPUパワーがあればネットワーク設定を調整することはよりよいゲーム体験を得る助けになります。ただ不適切な変更は実際の利益よりマイナスの副作用を起こすので、初期設定を使うことを推奨します。


=エンティティ補間=
=エンティティ補間=
�?期設定�?��?��?クライアント�?��?�よ�??一秒�?�20�?�スナップショットを�?��?��?�り�?��?�。も�?�ゲームワールド�?�オブジェクト(エンティティ)�?�サー�?�?�ら�?��?��?��?��?��?置�?��?��?��??画�?�れ�?��?��?��?�ら�?動�??オブジェクトやアニメーション�?��?�?則�?�ガクガク�?��?�る�?��?�ょ�?�。パケット�?��??失�?��?��?イ�?�も気�?��?��??よ�?��?��?都�?��?�起�?�る�?��?�ょ�?�。�?��?��?題を解決�?�るトリック�?�レンダリング�?��?��?��?�時間を戻�?��?��?�?置やアニメーション�?�最新�?�2�?��?�スナップショット�?�間�?�連続的�?�補間�?�る�?��?��?�も�?��?��?�。�?��?�テクニック�?�クライアントサイドエンティティ補間�?�呼�?�れ�?<code>cl_interpolate 1</code>�?�よ�?��?��?期設定�?�オン�?��?��?��?��?��?��?�。1秒間�?�20�?�スナップショット�?��?信�?�れる場�?��?新�?��?�更新情報�?�大体毎50ミリ秒�?��?��?�届�??�?��?�。も�?�クライアント�?�レンダリング時間�?�50ミリ秒�?��?��?�去�?��?�れ�?��?�れ�?��?エンティティ�?�常�?�最新�?�スナップショット�?��??�?�直�?�?�スナップショット�?�補間�?�続�?�る�?��?��?��?��??�?��?�。Source Engine�?��?��?�エンティティ補間を100ミリ秒�?�れ(<code>cl_interp 0.1</code>)�?�行�?��?��?��?��?�。�?�れ�?�より�?1�?��?�スナップショット�?��??失�?��?�も�?補間�?��??る2�?��?��?�当�?�スナップショット�?�存在�?�る�?��?��?��?�り�?��?�。以下�?�図�?�ワールドスナップショット�?�到�?�時間を示�?��?��?��?��?�:  
初期設定では、クライアントはおよそ一秒に20のスナップショットを受け取ります。もしゲームワールドのオブジェクト(エンティティ)がサーバから受け取った位置でしか描画されないのなら、動くオブジェクトやアニメーションは不規則でガクガクになるでしょう。パケットが損失した倍イでも気がつくような不都合が起こるでしょう。この問題を解決するトリックはレンダリングにおいて時間を戻して、位置やアニメーションが最新の2つのスナップショットの間で連続的に補間するというものです。このテクニックはクライアントサイドエンティティ補間と呼ばれ、<code >cl_interpolate 1</code >によって初期設定でオンになっています。1秒間に20のスナップショットが送信される場合、新しい更新情報は大体毎50ミリ秒ごとに届きます。もしクライアントのレンダリング時間が50ミリ秒だけ過去にずれていれば、エンティティは常に最新のスナップショットとその直前のスナップショットで補間し続けることができます。Source Engineはこのエンティティ補間を100ミリ秒遅れ(<code >cl_interp 0.1</code >)で行っています。これにより、1つのスナップショットが損失しても、補間できる2つの適当なスナップショットが存在することになります。以下の図がワールドスナップショットの到着時間を示しています:  


<center>[[Image:Interpolation.gif]]</center>
<center>[[Image:Interpolation.gif]]</center>


クライアント�?��?��?��?��?��?�最新�?�スナップショット�?�tick 344�?�?��?��?��?�る�?�10.30秒�?�も�?��?��?��?�。クライアント�?��?��?�る時間�?��?��?�スナップショット�?�クライアント�?�フレームレート�?�基�?��?��?�増加�?�る形�?�続�??�?��?�。新�?��?�画�?�フレーム�?�レンダリング�?�れる�?��??�?��?レンダリング時刻�?�クライアント時刻�?�10.32�?�ら画�?�補間�?�れ�?�0.1秒を引�?��?�も�?��?��?�り�?��?�。�?��?�例�?��?�引�?��?�時間�?�10.22�?��?�り�?�?��?��?��?�エンティティ�?��??�?�アニメーション�?�スナップショット340�?�342�?�間�?�補間�?�れ�?�正�?��?�断片を使用�?��?�も�?��?��?��?��?��?��?��?�。
クライアントが受け取った最新のスナップショットはtick 344、いいかえると10.30秒のものでした。クライアントにおける時間はこのスナップショットとクライアントのフレームレートに基づいて増加する形で続きます。新しい画面フレームがレンダリングされるときの、レンダリング時刻はクライアント時刻の10.32から画面補間遅れの0.1秒を引いたものになります。この例では引いた時間は10.22になり、すべてのエンティティとそのアニメーションはスナップショット340と342の間で補間された正しい断片を使用したものになっています。


100ミリ秒�?�補間�?�れ�?��?�る�?��?��?パケットロス�?�スナップショット342�?��??失�?��?��?��?��?�も補間を行�?��?��?��?��?��??�?��?�。�??�?��?��??�?�補間�?�スナップショット340�?�344を使�?��?��?�。も�?�2以上�?�スナップショット�?�連続�?��?�失�?れ�?�場�?��?補間�?�履歴�?ッファ�?�スナップショット�?��?��??�?��?��?��?��?��?��?��?完璧�?��?�動作�?��??�?��??�?�り�?��?�。�?��?�場�?�レンダラー�?�外挿法を使�?�(<code>cl_extrapolate 1</code>)今�?��?��?�履歴�?�基�?��?��?��?�純�?�線形外挿を行�?��?��?�。外挿�?�パケットロス�?�ら0.25秒�?��?�行�?れ�?��?�(<code>cl_extrapolate_amount</code>)。�?�れより長�??�?�る�?�予測エラー�?�大�??�??�?�り�?��?�る�?�ら�?��?�。
100ミリ秒の補間遅れがあるので、パケットロスでスナップショット342が損失したとしても補間を行うことができます。そのときは補間はスナップショット340と344を使います。もし2以上のスナップショットが連続して失われた場合、補間は履歴バッファのスナップショットがなくなってしまうため完璧には動作できなくなります。この場合レンダラーは外挿法を使い(<code >cl_extrapolate 1</code >)今までの履歴に基づいて単純な線形外挿を行います。外挿はパケットロスから0.25秒だけ行われます(<code >cl_extrapolate_amount</code >)。これより長くなると予測エラーが大きくなりすぎるからです。
 
エンティティ補間は常に100ミリ秒の画面「ラグ」を引き起こします。これはlistenサーバ(サーバとクライアントが同じマシン)で遊んでいるとしても同じです。そのため<code >sv_showhitboxes</code >をオンにしてサーバ時間でのプレイヤーヒットボックスを表示させると、描画されているプレイヤーモデルの100ミリ秒先に表示されることになります。これは他のプレイヤーに対して狙いをつけるときに先を狙わないといけないということではありません。というのもサーバサイドラグ補償がクライアントエンティティ補間について知っていて、この違いを直すからです。listenサーバにおいて補間をオフにすれば(<code >cl_interpolate 0</code >)、ヒットボックス表示と描画されるプレイヤーモデルが一致しますが、アニメーションと動くオブジェクトの表示はとてもガクガクになるでしょう。
エンティティ補間�?�常�?�100ミリ秒�?�画�?�「ラグ�?を引�??起�?��?��?��?�。�?�れ�?�listenサー�?(サー�?�?�クライアント�?��?��?�マシン)�?��?�ん�?��?�る�?��?��?�も�?��?��?��?�。�??�?��?��?<code>sv_showhitboxes</code>をオン�?��?��?�サー�?時間�?��?�プレイヤーヒットボックスを表示�?��?�る�?��?�??画�?�れ�?��?�るプレイヤーモデル�?�100ミリ秒先�?�表示�?�れる�?��?��?��?�り�?��?�。�?�れ�?�他�?�プレイヤー�?�対�?��?�狙�?�を�?��?�る�?��??�?�先を狙�?�?��?��?��?��?��?��?��?��?��?��?��?��?��?��?�り�?��?�ん。�?��?��?��?�もサー�?サイドラグ補償�?�クライアントエンティティ補間�?��?��?��?�知�?��?��?��?��?�?��?��?��?�を直�?��?�ら�?��?�。listenサー�?�?��?��?��?�補間をオフ�?��?�れ�?�(<code>cl_interpolate 0</code>)�?ヒットボックス表示�?��??画�?�れるプレイヤーモデル�?�一致�?��?��?��?��?アニメーション�?�動�??オブジェクト�?�表示�?��?��?�もガクガク�?��?�る�?��?�ょ�?�。


=入力予測=
=入力予測=
100ミリ秒�?��?ットワークレイテンシ�?��?�るプレイヤー�?��?進を始�?�?��?�仮定�?��?��?�ょ�?�。<code>+FORWARD</code>キー�?�押�?�れ�?��?��?��?�情報�?�ユーザコマンド�?��?存�?�れ�?サー�?�?��?られ�?��?�。サー�?�?��?��?��?�ユーザコマンド�?�移動(movement)コード�?�よ�?��?�処�?��?�れ�?�??�?�プレイヤー�?�キャラクタ�?�ゲームワールド�?�中�?��?進�?��?��?�。�?��?�ワールド�?�状態変更�?�全�?��?�クライアント�?�次�?�スナップショット更新時�?��?られ�?��?�。�??�?��?��?�?��?�プレイヤー�?�自身�?�移動�?�変化を歩�??始�?�?��?�ら100ミリ秒後�?�見る�?��?��?��?�る�?��?�ょ�?�。�?��?��?�れ�?�移動�?武器�?�発射�?��?��?�全�?��?�プレイヤーアクション�?�当�?��?��?�り�?�??�?��?�高レイテンシ�?��?��?�ら�?�悪化�?�る�?��?��?��?�る�?��?�ょ�?�。
100ミリ秒のネットワークレイテンシがあるプレイヤーが前進を始めたと仮定しましょう。<code >+FORWARD</code >キーが押されたという情報はユーザコマンドに保存され、サーバに送られます。サーバではこのユーザコマンドが移動(movement)コードによって処理され、そのプレイヤーのキャラクタがゲームワールドの中で前進します。このワールドの状態変更は全てのクライアントに次のスナップショット更新時に送られます。そのためこのプレイヤーは自身の移動の変化を歩き始めてから100ミリ秒後に見ることになるでしょう。この遅れは移動、武器の発射という全てのプレイヤーアクションに当てはまり、そして高レイテンシではさらに悪化することになるでしょう。
プレイヤー入力とそれに対応したビジュアルフィードバックの間の遅れは奇妙で不自然な感じを生み出し、正確に動いたり狙ったりするのを難しくします。クライアントサイドの入力予測(<code >cl_predict 1</code >)はこの遅れを取り除き、プレイヤーのアクションがより瞬時に感じるようにさせる方法です。サーバが自分自身の位置を更新するのを待つ代わりに、ローカルのクライアントが自分自身のユーザコマンドの結果を予測します。そのために、サーバがユーザコマンドの処理に使うのとまったく同じコードとルールをクライアントも実行します。予測が完了したら、ローカルのプレイヤーはその新しい場所に即時に移動します。この時サーバはまだ以前の位置にプレイヤーがいると見なしています。


プレイヤー入力�?��??れ�?�対応�?��?�ビジュアルフィード�?ック�?�間�?��?�れ�?�奇妙�?��?自然�?�感�?�を生�?�出�?��?正確�?�動�?��?�り狙�?��?�り�?�る�?�を難�?��??�?��?��?�。クライアントサイド�?�入力予測(<code>cl_predict 1</code>)�?��?��?��?�れを�?�り除�??�?プレイヤー�?�アクション�?�より瞬時�?�感�?�るよ�?��?��?��?�る方法�?��?�。サー�?�?�自分自身�?��?置を更新�?�る�?�を待�?�代�?り�?��?ローカル�?�クライアント�?�自分自身�?�ユーザコマンド�?��?果を予測�?��?��?�。�??�?��?��?�?��?サー�?�?�ユーザコマンド�?�処�?��?�使�?��?��?��?��?��?��??�?��?�コード�?�ルールをクライアントも実行�?��?��?�。予測�?�完了�?��?�ら�?ローカル�?�プレイヤー�?��??�?�新�?��?�場所�?��?�時�?�移動�?��?��?�。�?��?�時サー�?�?��?��?�以�?�?��?置�?�プレイヤー�?��?�る�?�見�?��?��?��?��?��?�。
100ミリ秒後に、クライアントは自分が予測したユーザコマンドによる変化を含んだサーバからのスナップショットを受け取ります。そこでクライアントはサーバでの位置と、予測した位置を比較します。もしそれらが違っているのなら、予測エラーが起こったことになります。このことはクライアントはユーザコマンドを処理したときに他のエンティティや環境について正しい情報を持っていなかったということを示します。そしてクライアントは自身の位置を訂正します。というのもサーバの情報がクライアントサイドでの予測より権威ある最終決定だからです。もし<code >cl_showerror 1</code >がオンになっていると、クライアントは予測エラーが起こったことを見ることができます。予測エラーの訂正はとても目立つことがあり、クライアントでの画面が突然飛ぶことがあります。このエラーを短い時間で段階的に直す(<code >cl_smoothtime</code >)ようにすることで、エラー訂正はスムーズになります。予測エラーのスムーズ化は<code >cl_smooth 0</code >でオフにできます。


100ミリ秒後�?��?クライアント�?�自分�?�予測�?��?�ユーザコマンド�?�よる変化を�?�ん�?�サー�?�?�ら�?�スナップショットを�?��?��?�り�?��?�。�??�?��?�クライアント�?�サー�?�?��?��?置�?��?予測�?��?��?置を比較�?��?��?�。も�?��??れら�?��?��?��?��?�る�?��?�ら�?予測エラー�?�起�?��?��?��?��?��?��?�り�?��?�。�?��?��?��?��?�クライアント�?�ユーザコマンドを処�?��?��?��?��??�?�他�?�エンティティや環境�?��?��?��?�正�?��?�情報を�?�?��?��?��?��?��?��?��?��?��?��?��?�を示�?��?��?�。�??�?��?�クライアント�?�自身�?��?置を訂正�?��?��?�。�?��?��?��?�もサー�?�?�情報�?�クライアントサイド�?��?�予測より権�?�?�る最終決定�?��?�ら�?��?�。も�?�<code>cl_showerror 1</code>�?�オン�?��?��?��?��?�る�?��?クライアント�?�予測エラー�?�起�?��?��?��?��?�を見る�?��?��?��?��??�?��?�。予測エラー�?�訂正�?��?��?�も目立�?��?��?��?��?�り�?クライアント�?��?�画�?��?��?然飛�?��?��?��?��?�り�?��?�。�?��?�エラーを短�?�時間�?�段階的�?�直�?�(<code>cl_smoothtime</code>)よ�?��?��?�る�?��?��?��?エラー訂正�?�スムーズ�?��?�り�?��?�。予測エラー�?�スムーズ化�?�<code>cl_smooth 0</code>�?�オフ�?��?��??�?��?�。
オブジェクトの振る舞いの予測は、サーバが実行するのと同じオブジェクトのルールと状態を知っている時のみ上手くいきます。これは通常事実とは違っています。サーバはクライアントに比べてより多くのオブジェクトの内部情報を知っているからです。クライアントは世界の一部だけを見ていて、オブジェクトをレンダリングするのに十分な情報だけを得ています。そのため、予測は自分自身のプレイヤーと、自分が操作する武器にのみ働きます。現時点では他のプレイヤーやインタラクティブオブジェクトの正確な予測が不可能です。
 
オブジェクト�?�振る舞�?��?�予測�?��?サー�?�?�実行�?�る�?��?��?��?�オブジェクト�?�ルール�?�状態を知�?��?��?�る時�?��?�上手�??�?��??�?��?�。�?�れ�?�通常事実�?��?��?��?��?��?��?��?�。サー�?�?�クライアント�?�比�?��?�より多�??�?�オブジェクト�?�内部情報を知�?��?��?�る�?�ら�?��?�。クライアント�?�世界�?�一部�?��?�を見�?��?��?��?オブジェクトをレンダリング�?�る�?��?��??分�?�情報�?��?�を得�?��?��?��?�。�??�?��?��?�?予測�?�自分自身�?�プレイヤー�?��?自分�?��?作�?�る武器�?��?��?��?�??�?��?�。�?�時点�?��?�他�?�プレイヤーやインタラクティブオブジェクト�?�正確�?�予測�?��?�?�能�?��?�。


=ラグ補償=
=ラグ補償=
プレイヤー�?�ターゲットをクライアント時間10.5�?�時点�?�撃�?��?��?��?��?��?�。�?��?�発射�?�情報�?�ユーザコマンド�?�詰�?込�?�れ�?�サー�?�?��?信�?�れ�?��?�。パケット�?��?ットワークを移動�?�る間もサー�?�?�ワールド�?�シミュレーションを続�?��?ターゲット�?�別�?��?置�?�動�?��?��?��?��?��?��?�能性�?��?�り�?��?�。ユーザコマンド�?�サー�?時間10.6�?�到�?��?��?プレイヤー�?�正確�?�ターゲットを狙�?��?��?��?��?�も当�?�ら�?��?��?��?��?��?��?��?�る�?�も�?�れ�?��?�ん。�?��?�エラー�?�サー�?サイド�?�ラグ補償(<code>sv_unlag 1</code>)�?�よ�?��?�訂正�?�れ�?��?�。
プレイヤーがターゲットをクライアント時間10.5の時点で撃ったとします。この発射の情報はユーザコマンドに詰め込まれてサーバに送信されます。パケットがネットワークを移動する間もサーバはワールドのシミュレーションを続け、ターゲットが別の位置に動いてしまった可能性があります。ユーザコマンドはサーバ時間10.6で到着し、プレイヤーが正確にターゲットを狙ったとしても当たらなかったことになるかもしれません。このエラーはサーバサイドのラグ補償(<code >sv_unlag 1</code >)によって訂正されます。
 
ラグ補償システムは約1秒ほど間の(<code >sv_maxunlag</code >で変更可能)全てのプレイヤー位置の履歴を保管します。ユーザコマンドが実行されるときに、サーバはそのコマンドが作成された時間を推定します。コマンド実行時間は以下のように計算されます:
ラグ補償システム�?�約1秒�?��?�間�?�(<code>sv_maxunlag</code>�?�変更�?�能)全�?��?�プレイヤー�?置�?�履歴を�?管�?��?��?�。ユーザコマンド�?�実行�?�れる�?��??�?��?サー�?�?��??�?�コマンド�?�作�?�?�れ�?�時間を推定�?��?��?�。コマンド実行時間�?�以下�?�よ�?��?�計算�?�れ�?��?�:


<pre>
<pre>
コマンド実行時間 = �?�在�?�サー�?時間 - クライアントレイテンシ - クライアント画�?�補間
コマンド実行時間 = 現在のサーバ時間 - クライアントレイテンシ - クライアント画面補間
</pre>
</pre>


�??れ�?�らサー�?�?�他�?�全�?��?�プレイヤをコマンド�?�実行�?�れ�?�時間�?��?�場所�?�巻�??戻�?��?��?�。ユーザコマンド�?��??�?��?�実行�?�れ�?当�?��?��?��?��?��?��?�正�?��??検出�?��?��?�。ユーザコマンド�?�処�?��?�れ�?�らプレイヤー�?�元�?��?置�?�戻�?�れ�?��?�。listenサー�?�?��?�<code>sv_showimpacts 1</code>を実行�?��?�サー�?�?�クライアント�?�ヒットボックス�?��?��?�を見る�?��?��?��?��??�?��?�:
それからサーバは他の全てのプレイヤをコマンドが実行された時間での場所に巻き戻します。ユーザコマンドはそこで実行され、当たったかどうか正しく検出します。ユーザコマンドが処理されたらプレイヤーは元の位置に戻されます。listenサーバでは<code >sv_showimpacts 1</code >を実行してサーバとクライアントのヒットボックスの違いを見ることができます:


<center>[[Image:Lag compensation.jpg]]</center>
<center>[[Image:Lag compensation.jpg]]</center>


�?��?�スクリーンショット�?�200ミリ秒�?�ラグ(<code>net_fakelag</code>を使用)�?��?�るlistenサー�?�?��?サー�?�?�当�?�りを確定�?��?�直後�?��?��?��?�も�?��?��?�。赤�?�ヒットボックス�?�100ミリ秒�?�?��?��?�クライアント�?��?�ターゲット�?置を示�?��?��?��?��?�。�??れ�?�らユーザコマンド�?�サー�?�?�届�??�?��?��?�間�?�ターゲット�?�左�?�移動を続�?��?��?��?�。ユーザコマンド�?�到�?��?��?�ら�?サー�?�?�推定�?�れるコマンド実行時間�?�基�?��?��?�以�?�?�ターゲット�?置(�?��?�ヒットボックス)を復元�?��?��?��?�。サー�?�?�射撃を追跡�?��?当�?��?��?��?��?�を確定�?��?��?��?�(クライアント�?��?�血�?�エフェクト�?�表示)。クライアント�?�サー�?�?�ヒットボックス�?�時間計測�?��?�?��?�正確性エラー�?�よ�?��?�完全�?��?�一致�?��?��?�ん。数ミリ秒�?��?��?��?��?��?��?��?�も速�??移動�?�るオブジェクト�?��?��?��?��?�数イン�?�?�エラー�?��?�り�?��?�。マル�?プレイヤー�?��?�当�?�り判定�?�ピクセル�?��?�?�完璧�?�も�?��?��?��?��??�?tickrate�?�移動オブジェクト�?�速度�?�よる正確�?��?��?界�?��?�る�?��?��?�知られ�?��?��?��?�。tickrateを上�?�る�?��?��?�当�?�り判定�?�正確性を増�?��?��?��?��?より多�??�?�CPU�?メモリ�?帯域能力�?�サー�?�?�クライアント�?��?��?��?�必�?�?��?�り�?��?�。
このスクリーンショットは200ミリ秒のラグ(<code >net_fakelag</code >を使用)があるlistenサーバで、サーバが当たりを確定した直後にとったものです。赤いヒットボックスは100ミリ秒前だったクライアントでのターゲット位置を示しています。それからユーザコマンドがサーバに届くまでの間にターゲットは左に移動を続けました。ユーザコマンドが到着したら、サーバは推定されるコマンド実行時間に基づいて以前のターゲット位置(青いヒットボックス)を復元しました。サーバは射撃を追跡し、当たったことを確定しました(クライアントには血のエフェクトが表示)。クライアントとサーバのヒットボックスは時間計測の小さい正確性エラーによって完全には一致しません。数ミリ秒の違いであったでも速く移動するオブジェクトにおいては数インチのエラーになります。マルチプレイヤーでの当たり判定はピクセル単位で完璧なものではなく、tickrateと移動オブジェクトの速度による正確さの限界があることが知られています。tickrateを上げることは当たり判定の正確性を増しますが、より多くのCPU、メモリ、帯域能力がサーバとクライアントにおいて必要になります。


疑�?も�?�る�?��?��?��?�ょ�?�。�?��?�当�?�り判定�?�サー�?�?�補償�?�れる�?��?��?�ょ�?��?�?当�?�り判定�?��?�プレイヤー�?置�?�巻�??戻�?��?�正確性エラー�?��?�対処�?�クライアントサイド�?�ら�?�簡�?��?�ピクセル�?��?�?�正確�?��?�行�?��?��?��?��?��??る�?��?�ょ�?�。�??�?��?�クライアント�?�プライヤー�?�撃�?�れ�?�場�?��?��?��?�部�?をやられ�?��?�を"当�?��?��?�"メッセージをサー�?�?�返�?��?��?��?��?�ょ�?�。�?�れを許�?��?��?��?��?��??�?��?��?��?��?ゲームサー�?�?��??�?�よ�?��?��?�?�?�決定を�?��?�る�?��?�クライアントを信�?�る�?��?��?��?��??�?��?��?�ら�?��?�。も�?�クライアント�?�"クリーン"�?�[[VAC]] (Valve-Anti-Cheat)�?�守られ�?��?��?��?��?��?�も�?パケット�?�ゲームサー�?�?�届�??間�?�サードパーティ�?�マシン�?�変更�?�れる�?�能性�?�残�?��?��?��?��?�。�?��?��?�"�?ートプロキシ"�?�VAC�?�検出�?�れる�?��?��?��??�?ットワークパケット�?�"当�?��?��?�"メッセージを挿入�?�る�?��?�も�?��??る�?��?�ょ�?�("中間者"攻撃�?��?�)。
疑問もあることでしょう。なぜ当たり判定がサーバで補償されるのでしょうか?当たり判定でのプレイヤー位置の巻き戻しと正確性エラーへの対処はクライアントサイドならば簡単にピクセル単位の正確さで行うことができるでしょう。そしてクライアントはプライヤーが撃たれた場合にどの部位をやられたかを"当たった"メッセージをサーバに返すことでしょう。これを許すことができないのは、ゲームサーバはそのような重要な決定をさせるほどクライアントを信じることができないからです。もしクライアントが"クリーン"[[VAC]] (Valve-Anti-Cheat)で守られていたとしても、パケットがゲームサーバに届く間にサードパーティのマシンで変更される可能性は残っています。ここで"チートプロキシ"がVACに検出されることなくネットワークパケットに"当たった"メッセージを挿入することもできるでしょう("中間者"攻撃です)。


�?ットワークレイテンシ�?�ラグ補償�?��?�実世界�?�比�?�る�?��?��?��?�的�?�パラドックスを生�?�出�?��?�能性�?��?�り�?��?�。例�?��?��?自分�?��?�蔽を�?��?��?�も�?�見る�?��?��?��?��??�?��?�攻撃者�?�ら�?�攻撃�?�当�?�る�?��?��?��?�り�?��?�。�?��?��?�起�?��?��?��?��?�サー�?�?��?��?��?��?�ヒットボックスを巻�??戻�?��?��?�?��?�攻撃者�?�見�?��?��?�る状態�?�移動�?��?��?��?��?��?��?��?��?��?�。相対的�?��?��?�パケットスピード�?��?��?��?��?��?��?整�?��?題�?�一般的�?�解�??�?��?��?��?��??�?��?�ん。�?�実世界�?��?��?��?��?��?��?��?題�?�気�?��?��?��?��?��?�軽�?�(パケット)�?�速�??移動�?��?�?��?��?�も他�?��?��?�も�?��?�世界を見�?��?�る�?�ら�?��?�。
ネットワークレイテンシとラグ補償は現実世界と比べると非合理的なパラドックスを生み出す可能性があります。例えば、自分が遮蔽を取ってもう見ることができない攻撃者からの攻撃が当たることがあります。ここで起こったのはサーバがあなたのヒットボックスを巻き戻して、まだ攻撃者に見えている状態に移動させたということです。相対的に遅いパケットスピードのせいでこの不整合問題は一般的に解くことはできません。現実世界においてはこの問題に気づかないのは軽い(パケット)は速く移動し、あなたも他のみなも同じ世界を見ているからです。


=�?ットグラフ=
=ネットグラフ=
Source Engine�?��?�クライアント接続スピード�?�質を�?ェック�?�る�?��?�?�ツールを�?��??�?��?��??供�?��?��?��?��?�。一番有�??�?�も�?��?��?ットグラフ�?��?<code>net_graph 2</code>�?�オン�?��?�る�?��?��?��?��??�?��?�。�?�信パケット�?��?��?�ら左�?�動�??�?�?��?�棒�?�表�?��?�れ�?��?�。�??れ�?�れ�?�棒�?�高�?��?�パケット�?�サイズを表�?��?��?��?��?�。も�?�棒�?�間�?�隙間�?��?�る�?��?�ら�?パケット�?�失�?れ�?��?��?順番�?�狂�?��?�到�?��?��?��?��?��?�。棒�?��?��?�れるデータ種類�?�よ�?��?�色分�?��?�れ�?��?��?��?�。
Source Engineではクライアント接続スピードと質をチェックするためのツールをいくつか提供しています。一番有名なものはネットグラフで、<code >net_graph 2</code >でオンにすることができます。受信パケットは右から左に動く小さい棒で表現されます。それぞれの棒の高さはパケットのサイズを表しています。もし棒の間に隙間があるのなら、パケットが失われたか、順番が狂って到着したかです。棒は含まれるデータ種類によって色分けされています。


�?ットグラフ�?�下部�?�左�?�列�?��?��?�在�?��??画フレームレート�?平�?�レイテンシ�?�??�?��?�<code>cl_updaterate</code>�?��?�在値�?�表示�?�れ�?��?��?��?�。真ん中�?�列�?��?�最新�?��?�信パケット(スナップショット)�?��?イトサイズ�?平�?��?�信帯域幅�?�??�?��?�一秒�?��?��?��?��?��?�パケット�?�表示�?�れ�?��?�。�?��?�列�?��?��?信データ(ユーザコマンド)�?��?��?��?��?��?�様�?�データ�?�表示�?�れ�?��?�。
ネットグラフの下部の左の列には現在の描画フレームレート、平均レイテンシ、そして<code >cl_updaterate</code >の現在値が表示されています。真ん中の列には最新の受信パケット(スナップショット)のバイトサイズ、平均受信帯域幅、そして一秒に受け取ったパケットが表示されます。右の列には送信データ(ユーザコマンド)についての同様のデータが表示されます。


<center>[[Image:Net graph2.jpg]]</center>
<center>[[Image:Net graph2.jpg]]</center>


=�?�照=
=参照=
[[Networking Entities]]
 
=忂照=
[[Networking_Entities|Networking Entities]]
[[Networking_Entities|Networking Entities]]

Revision as of 20:27, 29 November 2005

Source Engineでのマルチプレイヤーネットワーキング


概要

Source Engineのマルチプレイヤーゲームではクライアント/サーバネットワークアーキテクチャを使用しています。通常サーバは専用のホストとなってゲームを実行し、ワールドシミュレーション、ゲームルール、プレイヤーインプット処理に関して信頼できるもの(authoritative、訳注:ゲームロジック処理を集中して行うのはサーバ)になります。クライアントはゲームサーバに接続したプレイヤーのコンピュータです。クライアントとサーバはお互いに小さなデータパケットを高頻度(通常1秒に20から30パケット)で送りあいます。クライアントはサーバから現在のワールドの状態を受け取り、それらの更新情報をもとにビデオと音声のアウトプットを作り出します。クライアントはまた、入力デバイス(キーボード、マウス、マイクなど)からのデータをサンプルし、これらの情報をさらなる処理のためにサーバに送り返します。クライアントはゲームサーバとのみ通信を行い、クライアント同士の通信(peer-to-peer通信のような)を行いません。シングルプレイヤーゲームとは違い、マルチプレイヤーゲームにおいてはこのパケットに基づいた通信に起因する新しく多様な問題に取り組む必要があります。

ネットワーク帯域には限りがあるので、ワールドでの一つ一つの変更全てに対して、サーバが全てのクライアント向けに更新パケットを送り出すということは不可能です。その代わりに、 サーバは現在のワールドの状態を一定の間隔でスナップショットという形にし、これらのスナップショットをクライアントにブロードキャストします。ネットワークパケットがクライアント、サーバ間を移動するには時間がかかります(これがping時間です)。これにより、クライアント時間はサーバ時間より常に少し遅れているということになります。さらに、クライアントからのインプットパケットが届くのにも遅延があり、サーバは常に遅延したユーザコマンドを処理していることになります。追加して、他のバックグラウンドのトラフィックやクライアントのフレームレートのに影響されて、それぞれのクライアントのネットワーク遅れは様々で、しかも時間とともに変化します。こうしたのサーバとクライアントでの時間の違いは論理的な問題を引き起こし、ネットワークレイテンシ(遅延)が増加すると共に悪化します。早いペースのアクションゲームにおいては、たとえ数ミリ秒の遅れであってもラグのあるゲームプレイ感覚を引き起こし、他のプレイヤーを撃ったり、動くオブジェクトとインタラクションを行うことが難しくなります。帯域の制限とネットワークレイテンシに加え、情報がネットワークパケットロスで失われることもあります。

Networking1.gif

ネットワーク通信によって発生したこれらの問題全てに対処するために、Source Engineは複数のテクニックを使って、問題を解決、もしくは少なくともプレイヤーが問題に気づきにくくするようにしています。テクニックには、データ圧縮、補間(interpolation)、予測(prediction)、そしてラグ補償(compensation)があります。これらのテクニックが密接に組み合わされているので、1つのシステムの変更は他のシステムにも影響する可能性があります。このドキュメントではこれらのシステムの基本機能と、その連携について説明します。


ネットワークの基本

サーバはtickという非連続的な時間ステップを使ってゲームのシミュレーション計算を行います。初期設定では1秒に66のtickがシミュレーションされますが、MODでは独自のtickrate(1秒間に実行するtick数)を指定することができます。例えば[[Counter-Strike:_Source" title="Counter-Strike: Source">Counter-Strike: Source]]ではサーバCPU負荷を減らすためにこれより低い33 tick/秒の設定になっています。それぞれのtickにおいて、サーバは入力されたユーザコマンドを処理し、物理シミュレーションステップを実行し、ゲームルールをチェックし、全てのオブジェクト状態を更新します。tickのシミュレーションが終わったら、サーバはワールド更新が必要なクライアントがいるかを決定し、必要に応じて現在のワールド状態のスナップショットを作成します。tickrateが高くなるとシミュレーション精度が高まりますが、より多くのCPUパワー、そしてサーバ、クライアント両方の使用可能帯域が必要になります。サーバ管理者は初期設定のtickrateを-tickrateコマンドラインパラメータで上書きすることができますが、こうしたtickrateの変更はmodがデザインされたように動作しない可能性があるため推奨されません。

クライアントが使用可能な帯域は通常ごく限られたものです。最悪の場合においては、プレイヤーがモデムを使用していて、5-7KB/秒以上受け取れないということもありえます。もしサーバがそうしたプレイヤーにより大きなデータ量で更新情報を送ろうとした場合、パケットロスは避けることができないでしょう。そのため、クライアントはサーバに対して自身の受信帯域能力をコンソール変数rate (byte/秒)を設定して伝える必要があります。これがクライアントでの最も重要なネットワーク変数で、最適なゲームプレイ体験を得るためにはこれを正しく設定する必要があります。クライアントはcl_updaterate (初期設定20)を変更することでスナップショット頻度の要求をサーバに出すことができますが、サーバはシミュレーションのtick以上やクライアントの要求したrate以上のスナップショットを送ることはしません。サーバ管理者はクライアントが要求するデータ量をsv_minratesv_maxrate(どちらもバイト/秒)で制限することができます。スナップショット頻度はsv_minupdateratesv_maxupdaterate (どちらもスナップショット数/秒)で制限することができます。

クライアントはサーバのtick頻度と同じtick頻度で入力デバイスのサンプリングを行い、ユーザコマンドを作成します。ユーザコマンドは基本的にはそのときのキーボードとマウス状態のスナップショットです。しかしここではそれぞれのユーザコマンドについて新しいパケットを送信するのではなく、クライアントは決まった頻度(通常1秒に30回)でコマンドパケットを送信します。つまり1つのパケットの中で2つ以上のユーザコマンドが送信されることもあります。クライアントにおいてcl_cmdrateを変更することでコマンド送信頻度を増加させることができます。これにより反応性が上がりますが、より多くの送信帯域が必要になります。

ゲームデータはネットワーク負荷を減らすために差分圧縮(delta compression)を使って圧縮されます。つまりサーバは毎回完全なワールドスナップショットを送信するのではなく、直前の確認されたスナップショットから変化した部分(差分スナップショット)だけを送信します。クライアントとサーバの間に送信されるそれぞれのパケットには、データの流れを把握するために確認番号がつけられています。通常完全な(差分ではない)スナップショットはゲーム開始時や、クライアントが数秒の間重大なパケットロスに苦しんだ時だけに送信されます。クライアントはcl_fullupdateコマンドで手動で完全スナップショットのリクエストを出すことができます。

反応性、言い換えるとユーザが入力をしてからゲームワールドでのビジュアルフィードバックがあるまでの時間、は様々な要因によって決まります。サーバ/クライアントのCPU負荷、シミュレーションtickrate、データ転送量、スナップショット更新設定などもそれらの要因に含まれますが、大部分はパケットがネットワークを移動するのにかかる時間によるものです。クライアントがユーザコマンドを送信し、サーバが応答し、クライアントがそのサーバの応答を受け取るまでの時間はレイテンシping(もしくはラウンドトリップタイム)と呼ばれます。マルチプレイヤーオンラインゲームを遊ぶ場合、低レイテンシはかなり有利になります。予測(prediction)、そしてラグ補償(compensation)といったテクニックはこの有利さを最小限にして、遅い接続のプレイヤーも公正なゲームができるようにしようとするものです。必要な帯域とCPUパワーがあればネットワーク設定を調整することはよりよいゲーム体験を得る助けになります。ただ不適切な変更は実際の利益よりマイナスの副作用を起こすので、初期設定を使うことを推奨します。

エンティティ補間

初期設定では、クライアントはおよそ一秒に20のスナップショットを受け取ります。もしゲームワールドのオブジェクト(エンティティ)がサーバから受け取った位置でしか描画されないのなら、動くオブジェクトやアニメーションは不規則でガクガクになるでしょう。パケットが損失した倍イでも気がつくような不都合が起こるでしょう。この問題を解決するトリックはレンダリングにおいて時間を戻して、位置やアニメーションが最新の2つのスナップショットの間で連続的に補間するというものです。このテクニックはクライアントサイドエンティティ補間と呼ばれ、cl_interpolate 1によって初期設定でオンになっています。1秒間に20のスナップショットが送信される場合、新しい更新情報は大体毎50ミリ秒ごとに届きます。もしクライアントのレンダリング時間が50ミリ秒だけ過去にずれていれば、エンティティは常に最新のスナップショットとその直前のスナップショットで補間し続けることができます。Source Engineはこのエンティティ補間を100ミリ秒遅れ(cl_interp 0.1)で行っています。これにより、1つのスナップショットが損失しても、補間できる2つの適当なスナップショットが存在することになります。以下の図がワールドスナップショットの到着時間を示しています:

Interpolation.gif

クライアントが受け取った最新のスナップショットはtick 344、いいかえると10.30秒のものでした。クライアントにおける時間はこのスナップショットとクライアントのフレームレートに基づいて増加する形で続きます。新しい画面フレームがレンダリングされるときの、レンダリング時刻はクライアント時刻の10.32から画面補間遅れの0.1秒を引いたものになります。この例では引いた時間は10.22になり、すべてのエンティティとそのアニメーションはスナップショット340と342の間で補間された正しい断片を使用したものになっています。

100ミリ秒の補間遅れがあるので、パケットロスでスナップショット342が損失したとしても補間を行うことができます。そのときは補間はスナップショット340と344を使います。もし2以上のスナップショットが連続して失われた場合、補間は履歴バッファのスナップショットがなくなってしまうため完璧には動作できなくなります。この場合レンダラーは外挿法を使い(cl_extrapolate 1)今までの履歴に基づいて単純な線形外挿を行います。外挿はパケットロスから0.25秒だけ行われます(cl_extrapolate_amount)。これより長くなると予測エラーが大きくなりすぎるからです。 エンティティ補間は常に100ミリ秒の画面「ラグ」を引き起こします。これはlistenサーバ(サーバとクライアントが同じマシン)で遊んでいるとしても同じです。そのためsv_showhitboxesをオンにしてサーバ時間でのプレイヤーヒットボックスを表示させると、描画されているプレイヤーモデルの100ミリ秒先に表示されることになります。これは他のプレイヤーに対して狙いをつけるときに先を狙わないといけないということではありません。というのもサーバサイドラグ補償がクライアントエンティティ補間について知っていて、この違いを直すからです。listenサーバにおいて補間をオフにすれば(cl_interpolate 0)、ヒットボックス表示と描画されるプレイヤーモデルが一致しますが、アニメーションと動くオブジェクトの表示はとてもガクガクになるでしょう。

入力予測

100ミリ秒のネットワークレイテンシがあるプレイヤーが前進を始めたと仮定しましょう。+FORWARDキーが押されたという情報はユーザコマンドに保存され、サーバに送られます。サーバではこのユーザコマンドが移動(movement)コードによって処理され、そのプレイヤーのキャラクタがゲームワールドの中で前進します。このワールドの状態変更は全てのクライアントに次のスナップショット更新時に送られます。そのためこのプレイヤーは自身の移動の変化を歩き始めてから100ミリ秒後に見ることになるでしょう。この遅れは移動、武器の発射という全てのプレイヤーアクションに当てはまり、そして高レイテンシではさらに悪化することになるでしょう。 プレイヤー入力とそれに対応したビジュアルフィードバックの間の遅れは奇妙で不自然な感じを生み出し、正確に動いたり狙ったりするのを難しくします。クライアントサイドの入力予測(cl_predict 1)はこの遅れを取り除き、プレイヤーのアクションがより瞬時に感じるようにさせる方法です。サーバが自分自身の位置を更新するのを待つ代わりに、ローカルのクライアントが自分自身のユーザコマンドの結果を予測します。そのために、サーバがユーザコマンドの処理に使うのとまったく同じコードとルールをクライアントも実行します。予測が完了したら、ローカルのプレイヤーはその新しい場所に即時に移動します。この時サーバはまだ以前の位置にプレイヤーがいると見なしています。

100ミリ秒後に、クライアントは自分が予測したユーザコマンドによる変化を含んだサーバからのスナップショットを受け取ります。そこでクライアントはサーバでの位置と、予測した位置を比較します。もしそれらが違っているのなら、予測エラーが起こったことになります。このことはクライアントはユーザコマンドを処理したときに他のエンティティや環境について正しい情報を持っていなかったということを示します。そしてクライアントは自身の位置を訂正します。というのもサーバの情報がクライアントサイドでの予測より権威ある最終決定だからです。もしcl_showerror 1がオンになっていると、クライアントは予測エラーが起こったことを見ることができます。予測エラーの訂正はとても目立つことがあり、クライアントでの画面が突然飛ぶことがあります。このエラーを短い時間で段階的に直す(cl_smoothtime)ようにすることで、エラー訂正はスムーズになります。予測エラーのスムーズ化はcl_smooth 0でオフにできます。

オブジェクトの振る舞いの予測は、サーバが実行するのと同じオブジェクトのルールと状態を知っている時のみ上手くいきます。これは通常事実とは違っています。サーバはクライアントに比べてより多くのオブジェクトの内部情報を知っているからです。クライアントは世界の一部だけを見ていて、オブジェクトをレンダリングするのに十分な情報だけを得ています。そのため、予測は自分自身のプレイヤーと、自分が操作する武器にのみ働きます。現時点では他のプレイヤーやインタラクティブオブジェクトの正確な予測が不可能です。

ラグ補償

プレイヤーがターゲットをクライアント時間10.5の時点で撃ったとします。この発射の情報はユーザコマンドに詰め込まれてサーバに送信されます。パケットがネットワークを移動する間もサーバはワールドのシミュレーションを続け、ターゲットが別の位置に動いてしまった可能性があります。ユーザコマンドはサーバ時間10.6で到着し、プレイヤーが正確にターゲットを狙ったとしても当たらなかったことになるかもしれません。このエラーはサーバサイドのラグ補償(sv_unlag 1)によって訂正されます。 ラグ補償システムは約1秒ほど間の(sv_maxunlagで変更可能)全てのプレイヤー位置の履歴を保管します。ユーザコマンドが実行されるときに、サーバはそのコマンドが作成された時間を推定します。コマンド実行時間は以下のように計算されます:

コマンド実行時間 = 現在のサーバ時間 - クライアントレイテンシ - クライアント画面補間

それからサーバは他の全てのプレイヤをコマンドが実行された時間での場所に巻き戻します。ユーザコマンドはそこで実行され、当たったかどうか正しく検出します。ユーザコマンドが処理されたらプレイヤーは元の位置に戻されます。listenサーバではsv_showimpacts 1を実行してサーバとクライアントのヒットボックスの違いを見ることができます:

Lag compensation.jpg

このスクリーンショットは200ミリ秒のラグ(net_fakelagを使用)があるlistenサーバで、サーバが当たりを確定した直後にとったものです。赤いヒットボックスは100ミリ秒前だったクライアントでのターゲット位置を示しています。それからユーザコマンドがサーバに届くまでの間にターゲットは左に移動を続けました。ユーザコマンドが到着したら、サーバは推定されるコマンド実行時間に基づいて以前のターゲット位置(青いヒットボックス)を復元しました。サーバは射撃を追跡し、当たったことを確定しました(クライアントには血のエフェクトが表示)。クライアントとサーバのヒットボックスは時間計測の小さい正確性エラーによって完全には一致しません。数ミリ秒の違いであったでも速く移動するオブジェクトにおいては数インチのエラーになります。マルチプレイヤーでの当たり判定はピクセル単位で完璧なものではなく、tickrateと移動オブジェクトの速度による正確さの限界があることが知られています。tickrateを上げることは当たり判定の正確性を増しますが、より多くのCPU、メモリ、帯域能力がサーバとクライアントにおいて必要になります。

疑問もあることでしょう。なぜ当たり判定がサーバで補償されるのでしょうか?当たり判定でのプレイヤー位置の巻き戻しと正確性エラーへの対処はクライアントサイドならば簡単にピクセル単位の正確さで行うことができるでしょう。そしてクライアントはプライヤーが撃たれた場合にどの部位をやられたかを"当たった"メッセージをサーバに返すことでしょう。これを許すことができないのは、ゲームサーバはそのような重要な決定をさせるほどクライアントを信じることができないからです。もしクライアントが"クリーン"でVAC (Valve-Anti-Cheat)で守られていたとしても、パケットがゲームサーバに届く間にサードパーティのマシンで変更される可能性は残っています。ここで"チートプロキシ"がVACに検出されることなくネットワークパケットに"当たった"メッセージを挿入することもできるでしょう("中間者"攻撃です)。

ネットワークレイテンシとラグ補償は現実世界と比べると非合理的なパラドックスを生み出す可能性があります。例えば、自分が遮蔽を取ってもう見ることができない攻撃者からの攻撃が当たることがあります。ここで起こったのはサーバがあなたのヒットボックスを巻き戻して、まだ攻撃者に見えている状態に移動させたということです。相対的に遅いパケットスピードのせいでこの不整合問題は一般的に解くことはできません。現実世界においてはこの問題に気づかないのは軽い(パケット)は速く移動し、あなたも他のみなも同じ世界を見ているからです。

ネットグラフ

Source Engineではクライアント接続スピードと質をチェックするためのツールをいくつか提供しています。一番有名なものはネットグラフで、net_graph 2でオンにすることができます。受信パケットは右から左に動く小さい棒で表現されます。それぞれの棒の高さはパケットのサイズを表しています。もし棒の間に隙間があるのなら、パケットが失われたか、順番が狂って到着したかです。棒は含まれるデータ種類によって色分けされています。

ネットグラフの下部の左の列には現在の描画フレームレート、平均レイテンシ、そしてcl_updaterateの現在値が表示されています。真ん中の列には最新の受信パケット(スナップショット)のバイトサイズ、平均受信帯域幅、そして一秒に受け取ったパケットが表示されます。右の列には送信データ(ユーザコマンド)についての同様のデータが表示されます。

Net graph2.jpg

参照

Networking Entities

忂照

Networking Entities