「空島大乱闘」のオンラインの技術的なこと その3

伝説のマニアです♪U・ω・U


今回は、空島大乱闘のオンライン技術のうち、キー操作の同期化について説明していきたいと思います。

空島大乱闘では、十字キー(8方向)を使用しています。十字キーの実装方法については記事を分けましたので、下記を参照してください。

UnityのuGUIで十字キーを実装する



【キー操作同期化】
自分のプレイヤーはちゃんと操作したい
空島大乱闘では、自分のプレイヤー、他人のプレイヤー、敵キャラクターが出てきます。この中で、まず一番重要なのは、自分が操作しているプレイヤーです。

連載記事の「その2」で述べたように、空島大乱闘は、完全に各ユーザーを同期化することは妥協しています。しかし、せめて自分が操作するキャラクターは、自分が操作した通りに動いてほしいものだと思います。

よって、基本的に、空島大乱闘では、自分が操作するキャラクターは、自分が操作した通りに動いてくれます。

そして、同期化の方法として、自分が操作したこと(touch_began、touch_move等)を、他のプレイヤーに送る事によって、他のプレイヤーへ自分がどう動いたかを伝えています。

キー操作同期化だけではなく、空島大乱闘の実装にあたり全体的に意識していたのは、ユーザーが行った操作・結果についてはなるべくその通り同期しようという考え方です。

オンラインゲームでラグるのは当たり前ですが、一番ユーザーがイラっとするのが、「自分はこう操作したはずなのに、違う動きになった」「敵を殴ったはずなのに、殴った事にならなかった」というものです。なので、出来るだけユーザーが行った操作は尊重してその通りに同期化しよう、というのが基本方針でした。

キー操作のパケットについて
次に、キー操作時に、どういった情報を送るか説明します。空島大乱闘では、キー操作情報として、以下の情報を送っています。

・プレイヤーID・・・・・ゲームサーバーより割り振られたID
・プレイヤー位置情報・・プレイヤーのワールド座標位置値
・インプットタイプ・・・touch_began、touch_move等の種類
・キーステータス・・・・キーのステータス(上を押している、右を押している等)
・走ってるか否か・・・・プレイヤーが歩いているか、または走っているか

上記の情報を他のプレイヤーに送り、他のプレイヤーはこれを受けたら、その通りに送信したプレイヤーを動かしていきます。

送られてきたパケットの処理手順について
送信されてきたパケットを受けた後の、処理手順は以下の通りです。

(1)プレイヤーIDより、該当するプレイヤーを取得する
(2)プレイヤー位置情報を確認して、プレイヤーの位置がズレていた場合、位置を補正する
(3)キーステータスを、該当するプレイヤーへ適用する(インプットタイプによって処理は変わる)
(4)走っているか否かを確認して、該当するプレイヤーへ適用する

上記の流れでキー操作パケットは処理されています。

この内、(2)の位置補正については、トゥイーンで補正しています。ちょっとズレていた場合には、少しずつそのズレを修正するというものです。ただ、大幅にズレていた場合には、強制的にプレイヤー位置情報に従って、その位置へ移動させます(この場合、プレイヤーが瞬間移動しているように見えますw)。

また、(3)のキーステータスを、該当するプレイヤーへ適用すると、例えば、「右を押している」というステータスが適用された場合、そのプレイヤーは次のキー操作パケットを受信しない限り右へ移動し続けます。空島大乱闘でたまに、右にずっと移動していたプレイヤーが急にパッと(瞬間移動して)左に移動し始める場合がありますが、これは、「右を押している」というパケットを受信した後に、「左を押している」というパケットの受信が遅れたため起こる現象です。

あとは、走っているか否かを確認して、「右を押していて走っている」のであれば、右に走る処理を行い、「左を押して歩いている」のであれば、左に歩く処理を行う、という感じです。

パケットを送るタイミング
そしてキー操作の同期化で一番悩んだのが、キー操作パケットをどのくらいの頻度で、いつ送ればいいのか、という事です。頻度を上げれば同期化の精度は上がりますが、通信の負担が増えます。また頻度を下げ過ぎると、通信の負担は減りますが、頻繁に瞬間移動してしまうことになるでしょう。

空島大乱闘はどうしているかというと、かなり頻度を落としていますw

空島大乱闘で、キー操作パケットを送るタイミングは、以下の場合だけです。

・touch_beganが呼ばれた時
・touch_moveにより、キーステータスが変わった時
・touch_canceledが呼ばれた時
・touch_endedが呼ばれた時

連載記事の「その2」で述べたように、空島大乱闘はリレーサーバーを使っているため、あまり通信負担をかけることができません。なので、同期化の精度を落としてでも、負担を少なくしたいと思ったからです。

協力プレイであるため、何とかなりますが、これが対戦型となると、もっと精度を上げる必要があるかと思われます。



【他のキー操作同期化方法】
空島大乱闘では、上述のように、かなり頻度を落として同期化を行っていますが、他の方法として考えられるものを紹介していきます。

空島大乱闘をベースに頻度を上げる
単純に、空島大乱闘の実装方法にプラスして、定期的にキー操作パケットを送る、という方法が考えられます。この場合は、例えば、上述の送るタイミングに加えて、1フレームに数回、キー操作情報を送ります。

この場合は、インプットタイプ、キーステータス、走っているか否か、が変わらないのであれば、以下の情報送信だけで十分です。

・プレイヤーID
・プレイヤー位置情報

それでも、プレイヤーIDが2バイト、プレイヤー位置情報が8バイトなので、パケットの長さとしては全体で16バイトとなります。もちろんTCPヘッダ等を含めるともっと大きくなります(※パケットの細かい作成方法については連載の中で説明する予定です)。

プレイヤーの位置情報だけを送る
また、よくある実装方法として、プレイヤーの位置情報だけを送り(もちろん走っているか否か等の情報も送りますが)、それに合わせていく方法があります。この方法の場合は、位置情報を受けた側はトゥイーン等によりその位置へ移動させていくような処理を行います。

プレイヤーが目指す位置だけを送る
アクションゲームからは離れてしまいますが、この方法は、MMOG等でよく使われていた方法です。自分が行きたい位置をクリックするとその位置へプレイヤーが走っていく、というもので、その位置だけを他のプレイヤーへ送る方法です。
MMOGの場合は、リアルタイムアクションが難しいため(今となってはアクションMMOもあるようですがw)、出来るだけ通信を節約するため、この方法がよく使われているようです。



【まとめ】
まとめ。。。まとめというか、なんかもうアレです。同期化方法については悩みまくりですw

同期化方法はいくらでも考えられますが、ゲームシステム、想定される接続人数、通信環境、想定するクライアント端末、サーバースペック等色々と考慮して最善策を考えなければなりません。。。U・ω・U

。。。。そして私の場合は個人開発であるため、想定される接続人数なんて超少ないのです。しかし、急に増える(嬉しい)可能性も考えてスケーラビリティに作る必要があります(※この辺については連載の中で紹介していきます)。なので、必要なサーバー台数等の計算もやりにくいのですw

そして、結局色々と悩んだ挙句、最終的には「勘」という事に落ち着くのでした♪U・ω・U
テーマ: Unityゲーム制作 | ジャンル: コンピュータ

コメント

  • 2015/06/27 (Sat) 23:22
    No title

    テストだよ

    けんご #- | URL | 編集

コメントの投稿


管理者にだけ表示を許可する