HoI4 開発者日記 第184回 技術的なバグ修正2 屠龍 2019/6/12

スポンサーリンク
更新情報

Hearts of Iron IV 開発者日記 第184回目を紹介。

今回はバグ修正についてゲーム開発の技術的な面から解説した回になります

https://forum.paradoxplaza.com/forum/index.php?threads/hoi4-dev-diary-tech-bugaloo-ii-dragonslaying.1188942/

なお日記の原題にある、

Dragonslaying

というのは 第2次世界大戦の

川崎 キ45改 二式複座戦闘機 「屠龍」

を指すようです。(「とりょう」と読みます)

複座式戦闘機のこの名前が件名についているのは、
今回の日記がいつものpodcatさんに加えてもう1人、開発陣のプログラマーAndy Gaineyさんとの2人体勢による日記になっているためだと思われます。

では、内容を簡単に紹介してみたいと思います。

以下、パラドックスフォーラムの内容を意訳したものとなります。
正確を期すよう努めていますが詳細はパラドックスサイトの原文をお読みください。

[記事内の画像はパラドフォーラムより引用]

スポンサーリンク

Hearts of Iron IV 開発者日記 2019年6月12日分(第184回)

今回の日記担当はいつものHoI4″国防軍最高司令部“Podcatさん+開発陣のプログラマーAndy Gaineyさんです。

今回の日記、Podcatさんの分もAndy Gaineyさんの分もとても技術的な内容になっていて、私にはなかなか理解が難しい箇所が多かったです…😥
参考程度にお読みいただき、詳細は元ページの原文でご確認ください👻

Podcatさんの日記

冒頭のあいさつ

皆さんこんにちは!
今日の日記は、私が会議に出かけるのでちょっと短いものになるでしょう。

週末にHoI4 Ver1.7がリリースされて以降のテレメトリデータを調べたところ、同期ズレが発生しているマルチプレイヤーの数が以前よりも多いことがわかりました。
これは、新しいOOS問題が発生したことを示しています。
HoI4は再同期を行いますが、同期していないときはかなり面倒なことになります。
そこで小さなホットフィックスパッチ(1.7.1)について現在調査中です。
パッチがいつ準備ができているかについては、まだ我々がまだ少し確かでないETAを見つけ特定するため狩りを続けている状態なので、より慎重を要する可能性があります。
しかし、昨日この問題について確固たる解決の道筋が見えましたので、現在は良い解決策を考え出しています。

OOSとは非同期の事。

(警告!)技術的なセクションです:非同期(OOS)とは何ですか?

興味がある人のために、私はこれを少し掘り下げたいと思いました。
あなたが…普通の人間であれば、これを飛ばしても構わないと思います(笑)

同期ズレ(OOS)は、マルチプレイヤーゲームのホストとクライアントの動作が異なるときに発生します。
これはたとえば、一方のコンピュータではドイツが有利になり、もう一方のコンピュータではソビエトに有利になるという戦いのようなものです。
たいていの場合、あるユニットが他のユニットよりも1%高い組織を持っているといった状態の違いが早い段階で発見されます。
これが起こると、プレイヤー経験がすぐに発散し始めるので、私たちはやめてプレーヤーに警告します。
この時点で、ホストは「再同期」ボタンをクリックしてゲームを同期に戻すことができます。
再同期すると、ゲームの状態がリセットされ、現在のホストの状態がセーブゲームとして送信され、全員にロードされ、その後、処理が再開されます。

ではOOSの原因は何なのか?
ここが厄介なところで、問題が発生したときには、ほとんどいつも新しい事が理由になります。
ベースとなるコード・ライブラリの動作が異なる場合があるため、異なるプラットフォーム間で行うマルチプレーヤーが適している場合もあります。
その他の一般的な理由としてマルチスレッドがあります。
私たちは多くのコードをスレッド化していますが、同期を保つためにはイベントが世界に影響を与える場合でも、最終的にすべてのコンピュータで同じ順序で発生することを保証しなければなりません。
また不正なメモリ領域に触れるなど、予期しない方法でゲームの状態を変更する問題が発生する場合もあります(あるいはクラッシュもあります…。しかし、それらは簡単に見つけて修正できます!)。

OOSの発見と修正は、非常にまれにしか起こらないことが多く、正確に何であるかを理解するために多くのステップと反復を必要とするため、長い検証プロセスになる可能性があります。
それらを見つけるために、巨大なログファイル(全体的に全てが遅くなります)を吐き出す特別な設定でQAを使ってマルチプレーヤテストを実行し、OOSが起きたらログファイルとセーブ名を比較して何が違うのかを見ます。これにより、通常は検討を開始すべき領域が分かります。
たとえば、ユニットの組織が異なっているとします。これには、戦闘による損害、天候、供給不良など、さまざまな理由が考えられます。
そこで、関連するコード領域にさらにログを追加し、別のテストを行います。
うまくいけば私たちの推測のうちどれが正しいかを教えてくれるでしょう、そして更にこの分野のログと詳細について繰り返します。
もちろん、ログを追加してフレームレートを遅くすると、OOSエラーの中で最も面白いものが消えます(笑)

問題がプレイヤーとは無関係であれば、この検証のうちのいくつかは夜間に自動的に行うことができますが、そうではないことがよくあります。

問題を見つけて修正したら、通常はオープンベータパッチを作成し、問題が本当に修正されていることを確認し、あるいは問題が見つかったと確信できる場合は通常のパッチに直接進みます。
ベータパッチといえば、1.7のテストを助けてくれてありがとうございます!
私たちは、最終ビルドの前の週末に30,000ゲームセッションのテストに相当するデータを得ました。これはとても助けになりました!

HoI4開発の背景にあるいくつかの技術的な事柄に関するこの小さな考察が興味深いものであったことを願います。
疑問があれば遠慮なく質問してください!

このOOSを解決しようとしていないチームの一部は、1.8 ‘Husky’と次の拡張作業へと完全に移行しました。
ですが、その初期バージョンと私たちが皆さんに紹介できるものが出来上がるにはしばらく時間がかかります。
ですので、私達はラジオの沈黙(そしてすぐにやってくる栄光の社会主義国スウェーデンの夏休み!)に入り、今日の日記はしばらく間を置く前の最後の開発日記になるでしょう。

また後日お会いましょう!
1.7.1ホットフィックスの準備ができたかについてはフォーラムをチェックしてください。


以上

Andy Gaineyさんの日記

私はこの特定のOOS問題に取り組んでいるプログラマーです。
この問題を楽しもうという人のために技術的な詳細を紹介したいと思います。

OOSの改善

今回のOOS狩りの間、私たちは同期デバッグツールを複数の方法で改良しました。

  1. 動作中のOOSをキャッチしようとしたときに有効になる冗長ロギングシステムを再設計し、マシンが分岐し始めた正確な瞬間、どのマシンでもその分岐に気付く前にゲームがどういう振る舞いをしていたかについて把握しました。
    この作業ではログに書き込まれた最新のデータのみを対象としているため、古いデータはすべて定期的に破棄することで何GBものログを回避できます。
    これによりチームのハードドライブがいっぱいになることを心配することなく、ログをより詳細に記録できます。
  2. マルチプレイヤーセッション中にチームまたはQAがOOSを取得したときに各マシンがすべての関連ファイルを自動的に圧縮するようにログを収集することでファイルを保存するプロセスを合理化しました。
    誰もが自分のデータをバグレポートに追加したり、現在OOS攻撃を担当しているプログラマに直接送信したりするのが簡単になりました。
  3. ゲーム時間ごとに追跡するさまざまなシステム由来の雑多なデータ分散が増加したため、OOSにできるだけ早く気付く可能性が高くなりました。
    頻繁にチェックされていない小さなデータに触れると、同期がずれていることが多くなります。
    マシン間で何かがずれていることにゲームが最終的に気付くと、非常に多くのデータが異なるため、最初に同期がとれなかったデータが何であるかを識別することはほとんど不可能です。
    そのためOOSをすばやく見つけるほど、それを理解して修正するチャンスが増えるのです。
  4. 私たちは現在、他のスレッドで同時に変更されている可能性がある1つのスレッドでデータの読み書きを行わないようにするため、ゲームの内部開発者ビルドにチェックを含めるようにしました。
    これはシングルプレイヤーゲームでも実行され、コードの一部がOOSを引き起こす可能性があることをした、という正確な瞬間にプログラマに対して警告を発します。
    それでもなお、チェックを適切な場所に分散させる必要はありますが、カバレッジが広くなるにつれて、卑劣なOOSリスクに対する保護が強化されます。

現在のOOS問題に対する私たちの手段はは、4の項目に関連しています。
各国には自分のユニットで何をしたいのかを把握するための独自のスレッドがあります。
その後、実際には1つのスレッドにおいて、一度に1つの国でこれらの計画を実行します。
通常これは問題ありませんが、義勇兵は少し特別になっていて、ある国によって統制されてはいますが他の国の状況の中で活動しています。

師団を水上に移動させるための特別なコードがあり、そこでは輸送に利用できる十分な輸送船があるかどうかをチェックします。
(義勇兵の場合、これは送信国のスレッド内でチェックされますが、受信国の輸送船を使用します。)。
輸送船が十分にある場合は、すべてが単一のスレッドで実行され、順序に依存する差異のリスクがないときに、後で実行するために移動アクションを保留キューに追加します。そうしないと、アクションはキューにまったく追加されません。

残念ながら、ごくまれなケースでは、受け入れ国側に十分な輸送船がほとんどなく、スレッドのタイミングが異なるために状況が悪くなることがあります。
1台のマシンが義勇兵の支配国を先に処理し、他の目的のために受入国のスレッドが残りの輸送船団を消費する前に移動行動を待ちキューに入れます。
その間、別のマシンが先に受入国を処理するために回避し、送付国が水上で義勇兵を移動することを検討する前に輸送船を消費します。
それで最初のマシンは十分な輸送船があると信じて海上輸送を始めようとします。
そして二番目のマシンはとにかく輸送のための十分な輸送船がないであろうという理由でユニットをそれが現在居る場所に留まらせます。バム!つまり同期していません。

これを修正するために、数層による保護を追加しようとします。
まずキューに入れられたアクションを実行するときに、2度目の輸送船カウントを検証し、不十分な輸送船数の場合はアクションをスキップします。
これはすべてのマシンがこの実行フェーズで合意することを意味します。
利用可能な輸送船数について信頼できないより不安定な期間中に、待機中の行動を同期させておくために、義勇兵は、別のスレッドによって変更される可能性のある、実際に現在の船の数ではなく、最後に確認され安定した輸送船数をチェックするようになります。

そしてポイント4で指摘したように、我々はある国の輸送船団の状況を読みとりたいコードが、安全な状況の中で実行されていることを確認できるよう輸送船団のチェックを追加しました。もし実行できなければ、すぐにブレークし、プログラマーに不適切なコードであると警告します。

これにより1.7で発生した同期外れの増加を解決できるだけでなく、他のすべてのツールの改善により通常の開発中に新たに発生したその他の同期外れの問題を検出できるようになるのです。


以上

振り返り感想

まずVer1.7では同期ズレの問題が発生していて、それに対する修正が1.7.1としてリリース予定とのことです。

そしてHoI4開発者日記はしばらくお休みとのこと。
とりあえずスウェーデンの夏休みが終わるまでということですが、去年は7月11日の日記(145回)で一旦お休みに入って、8月1日の(146回)ではもう殆どのメンバーが夏休みが終わって復帰したと書かれていました。

ということで、次回は8月ぐらになるのかもしれません。
ただ、それまでに1.8に関して紹介できる状態に仕上がっていなければまだ日記は再開されないと思います。

いずれにせよ、しばらく開発者日記はお休みなのでこのサイトでの紹介もお休みになります。

またそのうちお会いしましょう!

HoI4 開発者日記 第184回 2019年6月12日分は以上となります。