遅延同期方式(後で口裏合わせようゼ方式)

注意:文章化することで、この方式の”弾丸発射”の部分で、まずい点が発覚してしまいました(^_^;)。例によって勘違いしている可能性もあります。

長所

プレイヤの入力した結果が即座に画面に反映されます。フレーム同期方式の場合、レイテンシの分反応が遅れてしまいますからね。

データの送信間隔を長くしても、ある程度までOKです。

短所

表示と結果が食い違います。データの送信間隔が長くなればなるほどそれが顕著です。

場合によっては他のプレイヤが他のプレイヤに食い込んだり、他のプレイヤが壁に食い込んだりします(^_^;)。

移動スピードが速いゲームでは、上の二つの欠点がかなり顕著に表れます。ので、そのようなゲームではこの方式を採用すると悲惨なことになります。

で、どのようなもの?

他のプレイヤのステータス更新を①一定時間(300〜400msぐらい?)遅らせるのです。遅らせた時間の間にパケットが着てもらえばOKなので、フレーム同期に比べてレイテンシに対して厳しくありません。しかし、ただ単に表示するだけならばこれだけでOKなのですが、他のプレイヤに干渉するイベント(例えばプレイヤが他のプレイヤに当った、プレイヤが弾丸を発射した等)がおきた場合、工夫しないと各クライアントで結果がてんでばらばらになってしまいます。つまり、イベントの同期を考えなければならないのです。そこで、”描画が少々(?)まずくても、結果が同期すりゃいいんじゃないの?”を合言葉に、イベント同期について考えてみました。

工夫その1(弾丸発射)

nyonyoru、kaf、n_ryotaの三人がネットゲームをしていたとしましょうこの仮定はフィクションであり、実際のハンドル名とはなんの関係もありません(ぉ。そして、あるときnyonyoruが弾丸をあさっての方向に発射したとします。このとき、nyonyoruの画面には弾丸が発射されているのが即座に表示され、kaf、n_ryotaには”弾丸を発射したから、そこんとこよろしくね!”というメッセージを送ります。そして②ある程度の時間がたった後、そのメッセージがkaf、n_ryotaへ届きました。ここからが重要です。nyonyoruは過去のkaf、n_ryotaの位置を見て発射したのですから、(①+②)時間前にnyonyoruから弾丸が発射された、と考えます。というわけで、kaf、n_ryotaは各々時間を巻き戻して、①+②時間前に弾丸を発射されたものとして当り判定を行います。その後は普通に弾丸を飛ばしておけばよいわけです。
さて、今度は別の場合を考えてみましょう。nyonyoruがkafに向かって弾丸を発射して、よけきれずにkafが当ってしまった場合です。この場合、当然弾丸は消滅するわけですが、①時間前のkafの情報しかわからないn_ryotaには、弾丸の消滅は確認できないのです。つまり、もしn_ryotaが弾丸の延長線上にいた場合、本来無いはずの弾丸に当るというなんとも理不尽なことがおきてしまう、というわけです。これを解消するためには、n_ryotaは①時間前のkafと①時間前の弾丸との当り判定を行います。その後、現在の時間のn_ryotaと現在の時間の弾丸と当り判定を行います(すべての弾丸は貫通弾、という手もあり(^_^;))。n_ryotaにとっては弾丸が突然消えてkafが突然ダメージを受けるように見えますが、実は今まで見ていたものは嘘で、今この瞬間に起きたことが真実なのです(^_^;)。
しかし、これでもまた問題が起きてしまいます。実際に弾丸が消滅した時間と、n_ryotaが弾丸の消滅を確認できる時間には、若干間があります。もしその間にn_ryotaが弾丸に当ってしまった場合、今までの苦労が水の泡です。これの解決策は、かなりとんでもない方法なのですが、n_ryotaが当ったことを無かったことにするのです。n_ryotaはあたったはずの弾丸からダメージを食らわなくておかしく感じますが、おかしく感じるのはn_ryotaだけで、nyonyoru、kafにとってはそれで正しいのです(^_^;)。

このように、この”遅延同期方式”は、つじつまを合わせるために有る特定の人々に(①時間の間だけですが)嘘を教える方法なのです。移動スピードが速いゲームだと悲惨なことになる理由、わかってもらえたでしょうか?

DIABLO式との比較

某IRCで玉砕してしまったこの方法なのですが、女々しくもDIABLO式の同期方法と比較した結果、以下のようなことがわかりました。

若干レイテンシが少ない

DIABLO式では、弾丸が当った場合、”弾丸を発射した”という情報と”弾丸が当った”という情報という二つの情報を送信することになります。一方、僕の方法は弾丸を発射した後は各々が当り判定を行うので、”弾丸が当った”とう情報を送信する必要がありません。

ただし、これは攻撃と被弾にタイムラグがある場合のみ有効です。攻撃した時点で命中したかどうか決まってしまう場合は、この方式は意味を持ちません。

面倒

DIABLO方式の方がプログラミングが圧倒的に楽です。

で、結論なのですが、たかが一回の送信をケチるために面倒なプログラミングをする覚悟がある方は、僕の方法を採用してください(-_-;)。

工夫その2(当り判定)

色々考えたのですが、ある意味究極の方法”相手に干渉しない”があるので、とりあえずこれを紹介します。

この方法は、要するに相手に当った場合、当られた相手は何事も無かったかのように進み、当った側だけが吹き飛ばされるようにするのです。相手は位置が全くずれないので、イベント同期をとる必要がありません。

問題が発覚しました。他のプレイヤ同士がめり込んでしまう可能性があることです。自分と他のプレイヤとの当り判定の場合、他のプレイヤの位置は過去の位置なので時間的にずれがあるのですが、他のプレイヤと他のプレイヤのあたり判定の場合はお互いともに①時間分ずれているので、時間的なずれが無いのです。

以下製作中・・・