モバイルMMO RTSの開発の機能。 パート2

こんにちは ごく最近、私はStormfall:Rise of Balurの作業方法について話し始め、プロジェクトのクライアント部分をUnityで記述しました。 今日は、スキニング、マルチスレッド、接続不良のネットワークでの作業、およびクエリキャッシュへのアプローチについて説明します。







スキンとそれらを使用する



RTSジャンルは、1つのエンジンに基づいて異なる設定にうまく適応します。 このようなゲームがいくつかあります。 プロジェクトを書くとき、UI、UX、ゲームプレイロジックなど、多くの変更があります。 図書館と社会サービスの統合に関する特定の要件が表示される場合があります。 ゲームを設計するとき、アーキテクチャの要件を定めて、コードの最大限の共有を維持する必要がありました。



UIの動作をカスタマイズするために、リソースからプレハブを動的にロードすることからUIオブジェクトの作業を開始することにしました。 その後、特定のViewスクリプトが実行されます。これは、ViewModelの特別なクラスに関連付けられています。 モデル自体はすべての機能をサポートするように作成されています。これは、モデルがサーバーを反映​​しており、サーバーからログインするときに設定されるためです。







Unityには、プロジェクトの説明を含むファイルがありません。Assetsフォルダーにあるすべてのコードは、最終的にビルドになります。 このような状況では、共通のコードベースで複数のプロジェクトを作成することは困難です。 プロジェクトがUnityプロジェクトの形式ではなく、必要な形式である共通リポジトリを使用することにしました。



コードフォルダーへのシンボリックリンクを作成するスクリプトを使用して、Unityプロジェクトをデプロイします。 必要に応じて、開発ビルドを展開します。 他のプロジェクトからのコードを含む、すべてのコードが含まれています。 これは、たとえばリファクタリングに必要ですが、ゲームプレイには影響しません。



Stormfallのマルチスレッド:Rise of Balur



モバイル市場が勢いを増しているとき、開発者はアプリケーションにマルチスレッドが必要かどうかを議論しました。 今、これは議論の問題ではありません。 マルチスレッドにより、いくつかの問題を解決します。



  1. ThreadPoolからスレッドへのサーバーへのコールバック要求の実行。 コマンド自体は、WebRequestの実行に加えて、送信されたデータをJSON形式でシリアル化し、応答を逆シリアル化します。 また、応答に含まれる新しいデータでモデルを更新するプロセスも実行します。
  2. 別のスレッドでモデルを更新するメカニズムのロジックの実行。 このメカニズムは1秒間に1回機能し、かなり長い時間実行できます。


モデルデータアクセスメカニズムはモニターを介して機能し、さまざまなデータブロックポリシーをサポートします。 同時に多くのオブジェクトへの読み取りアクセスを許可しますが、これをモデルへのデータの書き込みと組み合わせることはできません。



Unityでは、非主流のエンジンを使用することはできません。 アプリケーションを設計する際にはこれを念頭に置いて、メインスレッドをオフロードして、非UIデータの処理を他のスレッドに移してください。







悪いネットワーク接続



Stormfall:Rise of Balurでは、サーバーとの対話はHTTPリクエストを介して行われます。 リクエストエラーが発生した場合、エラーが発生した段階と、リクエストがサーバーで実行されたかどうかを常に判断できるわけではありません。 モバイルゲームは、常に安定しているとは限らないモバイルインターネットを介して機能することを覚えておく必要があります。 ユーザーに快適なゲームプレイを提供するために、いくつかのアプローチを実装しています。



  1. 楽観的なクエリの実行。
  2. ユーザー要求がオーバーフローしました。 このメソッドは、リクエストがデータの変更に関するものであり、クライアントに戻ったときに中断した場合に、コマンドの二重実行を防ぎます。


次に、各アプローチについて詳しく説明します。



楽観的なクエリ実行



要求コマンドにメカニズムを実装しました。これにより、実行中のUIロックを回避できます。 リクエストの実行が開始された後、サーバーが正常なレスポンスを返すようにモデルを変更します。 答えが本当に成功した場合、何も変更したり、サーバーからの応答でモデルを補完したりしません。 サーバーがエラーを返した場合、初期段階で行われた変更のロールバックメソッドを呼び出し、エラーをユーザーに通知します。



これのために正確に何をしましたか:



  1. 別のタイプのコマンドを実装しました。これは、サーバーの応答を待たずに、リクエストを事前に実行する可能性を記述しています。
  2. 彼らはキューを使用してリクエストを厳密に連続して実行させました。 アクティブと保留の2つの要求を含めることができます。 ユーザーが多くのアクティビティをスケジュールできるようにしたくないため、それらは非常に少数です。 最初のコマンドがエラーを返した場合、他のすべてのコマンドをキャンセルする必要があります。キャンセルしないと、コマンドの実行によりデータの不整合が発生します。 ユーザーがゲームを終了できることを除外しません。また、コマンドのキューは実行のためにサーバーに送信されません。 キューがいっぱいの場合、待機ウィンドウがユーザーに表示されます。
  3. リクエストの実行エラーが発生した場合、実行されたすべてのアクションがロールバックされ、キュー内の次のリクエストが存在する場合はキャンセルされます。 アクションのロールバックは手動でプログラムされます。


サーバー側の編集キャッシング



2番目のアプローチの実装に移りましょう。



  1. クライアントがサーバーへの要求時にネットワークエラーを受け取った場合、クライアントは要求を再送信しようとします。
  2. 各リクエストには独自の識別子があります。
  3. 要求がいっぱいになった場合、試行番号もヘッダーに書き込まれます。
  4. 後続のリクエストごとに、タイムアウトは10秒から20秒に増加します。これは、ユーザーのインターネットが貧弱で、割り当てられた時間内にサーバーから大きな応答をダウンロードするのに十分な速度がない場合に行いました。 これは意味がないように思えるかもしれませんが、すぐに最大値を設定できます。 実際には、ネットワーク上の理由でドロップされたリクエストは、最小間隔で繰り返されることが判明しています。 これは、最大タイムアウトを待ってリクエストを再試行するよりも優れています。
  5. すべてのリクエストが失敗した場合、エラーに関するユーザー情報を表示し、ネットワークエラーの最大数に達した場合、セッションを継続できないと考え、ユーザーにゲームを再起動することをお勧めします。
  6. サーバー側では、各ユーザーの最後のいくつかの編集要求が短時間キャッシュされます。 既に実行された識別子を持つリクエストを受信すると、キャッシュされた結果が返されます-もちろん、存在する場合。 そうでない場合、サーバーはエラーを返します。
  7. 読み取り要求はキャッシュされず、常にサーバーによって再度処理されます。


統計によると、要求の0.76%はキャッシュから取得され、これは130番目のユーザー要求ごとです。



第三部でお会いしましょう! UnityでMMO RTSを作成するサイクルの始まりを逃した場合は、 こちらをご覧ください



シリーズの他の記事:






All Articles