ホーム > mixiニュース > IT・インターネット > IT総合 > 青山Pが振り返る「ドラゴンクエストX」3つの失敗――消すつもりのコードが本番環境に

青山Pが振り返る「ドラゴンクエストX」3つの失敗――消すつもりのコードが本番環境に

0

2019年03月15日 11:52  @IT

  • チェックする
  • つぶやく
  • 日記を書く

@IT

写真スクウェア・エニックス 第6ビジネス・ディビジョン 青山公士氏
スクウェア・エニックス 第6ビジネス・ディビジョン 青山公士氏

 翔泳社は2019年2月14〜15日に「Developers Summit 2019」を開催した。本稿では、スクウェア・エニックスでドラゴンクエストXのプロデューサーを務める青山公士氏の講演「ドラゴンクエストXを支える失敗事例」の内容を要約してお伝えする。



【画像:失敗の原因】



 青山氏は「ドラゴンクエストX オンライン」(以下、「ドラゴンクエストX」)で起きた3つの不具合とその原因を取り上げ、ドラゴンクエストX開発陣が不具合から得られた教訓を紹介した。



●ドラゴンクエストXはどのように開発、実装されているか?



 ドラゴンクエストXは、各ユーザーがゲームクライアントを通じてサーバに接続し、ゲームをプレイするMMORPG(Massively Multiplayer Online Role-Playing Game)だ。開発では、さまざまな機能拡張や期間限定イベントの実施を見据えて柔軟に対応できる「運営」と、不具合修正や障害対応ができてサービスを継続して提供できる「運用」の2つを重視している。



 ゲームの実装はC++言語で、バージョン管理ソフト「Subversion」やプロジェクト管理ソフト「Redmine」を活用している。さらに、botがゲームをプレイしてゲームの進行に問題がないかどうかテストを実施しているという。



 青山氏は、ドラゴンクエストX開発初期から現在までに生まれた累計約20万の不具合(バグ)、タスクの中から、以下の3つを取り上げた。どのような不具合なのか、何が原因で起きたのかを見ていこう。



1. 「キラージャグリング」「ゴッドジャグリング」の効果音が鳴り続いたり、ノイズが発生したりすることがある。



2. 2017年6月10日土曜日の更新以降、「邪神の宮殿」で「同盟の仲間を自動で探す」を選択しても、パーティーが組まれない場合がある。



3. 「釣り」において、「オウムガイ」の「ビッグサイズ」や「キングサイズ」を釣ったのに、「釣り老師」や「魚交換員」から、ビッグサイズはノーマルサイズ、キングサイズはビッグサイズとして扱われることがある



●1.再現が難しいエフェクトの不具合



 初めに取り上げた不具合は「『キラージャグリング』『ゴッドジャグリング』の効果音が鳴り続いたり、ノイズが発生したりすることがある」だ。複数回ダメージを与える「キラージャグリング」や「ゴッドジャグリング」という攻撃スキルを発動させた際、攻撃が終了しても効果音が止まらずに鳴り続ける不具合が発生するようになった。



 「問題となっている不具合を確認しようにも、発生するタイミングをつかめないため、調査が難航した。長時間にわたる調査の結果、別の戦闘スキルにまつわる不具合修正のため、音声停止処理を無効化したせいで、この不具合が引き起こされていた(エンバグ)と分かった」



 攻撃スキルを発動すると、アクション音が流れた後、アクション音の再生を終了する処理が行われる。そして、敵に当たった場合は「ヒット音」、敵に攻撃をかわされた場合は「ミス音」が再生される。しかし、他の攻撃スキルの内部検証中、ミス音が再生される前に効果音終了の処理が入ると不具合になるという問題が発生した。そのため、他の攻撃スキルでも起きる可能性を考慮し「ミス音の前の効果音終了処理を無効化」してゲームを更新した。その結果、先述した2つの攻撃スキルの発動後、ミス音再生時に効果音が流れ続けてしまう不具合が発生してしまった。



 「最終的に、他の攻撃スキルの不具合対応は専用処理で対応し、ミス音再生前の効果音停止処理は再度有効化した。この不具合対応から得た教訓は、システムを改修する際、できるだけ影響範囲を極力狭くなるように調整し、バグトラッキングシステム(BTS)のチケットに影響範囲を明記して、更新する際に問題がないかどうか全影響範囲の再検証を行うべしということだ」



●2.データ移行時に利用したコードによる不具合



 次に取り上げた不具合は、「2017年6月10日土曜日の更新以降、『邪神の宮殿』で『同盟の仲間を自動で探す』を選択しても、パーティーが組まれない場合がある」だ。8人で協力して敵と戦う「邪神の宮殿」というコンテンツで、参加希望者が8人いてもパーティーが組まれなくなるという、「オートマッチング」機能の不具合が発生した。



 パーティーの参加条件は「職業が占い師であること」など、ゲーム内のプレイに制限をかけるもので、毎月10日と25日の午前6時に参加条件が自動更新される仕組みになっている。



 「参加条件はゲームプランナーが作成した条件データを用いている。ゲームクライアント側で条件データを利用して、パーティーに参加できる条件を満たしているかどうかをチェックした後、ゲームサーバ側に用意された参加条件ロジックと照らし合わせてマッチングを行っていた。しかし、特定のエリアでパーティーが組まれなくなってしまった。ゲームサーバのソースコードを調査した結果、以下のソースコードが見つかった」



 このソースコードによる処理が行われた結果、特定のエリアで、プランナーの条件データでマッチする人と、ゲームサーバ側の条件データでマッチする人が完全に異なる状態になり、パーティーが成立しなくなった。なぜこのコードがゲームサーバに残っていたのか、青山氏は説明する。



 「この不具合が起きる1年前の6月、邪神の宮殿に関するデータフォーマットを変更した。その際、移行するタイミングが不明瞭だったため、一時的に6月分の参加条件をソースコードで直接処理することでシームレスに移行できるようにした。そのソースコードを消し忘れて、1年後の6月10日に分岐処理が行われて不具合が発生したというオチだった。この失敗からは、暫定で対応する際は対応完了までをBTSのチケットで管理すべきだという教訓を得た」



●3.浮動小数点にまつわる不具合



 最後に取り上げた不具合は「『釣り』において、『オウムガイ』の『ビッグサイズ』や『キングサイズ』を釣ったのに、『釣り老師』や『魚交換員』から、ビッグサイズはノーマルサイズ、キングサイズはビッグサイズとして扱われることがある」だ。



 ドラゴンクエストXでは、釣りを行うことができる。魚は個々に大きさの数値データとサイズの定義があり、サイズとしては「キング」「ビッグ」「ノーマル」がある。魚を釣った後、「釣り老師」や「魚交換員」というキャラクターと話すと、サイズに対応した報酬を得られる。



 不具合の対象となった「オウムガイ」という魚は「1023mm」(1.023m)以上でビッグサイズ、「1022mm」(1.02m)以下でノーマルサイズと定義されていたが、ビッグサイズのオウムガイがノーマルサイズと判定されていた。



 「釣りの実装部分ではC++とLuaを併用しており、C++では魚の大きさをint型で扱っていた。一方、LuaにはC言語におけるdouble型しかないため、doubleで扱っていた。われわれはLuaにおけるdouble型の数値演算で浮動小数点の誤差による不具合が起きたのではないかと疑った」



 浮動小数点の誤差とは、小数に関するプログラムの問題だ。コンピュータの内部では10進数を2進数として扱うが、0.1のような小数を2進数で表現しようとすると10進数における「3分の1 = 0.333……」のような循環小数になる。従って、数値演算で小数を扱う場合は、近似値計算が行われている。



 今回の場合、1023mmから1.023mに変換する計算の中で、限りなく1023に近い値と、限りなく1.23に近い値を利用している。開発チームでは1023や1022という値に1000を掛けたり、割ったりして内部の値がどうなるか確認した。その結果「1023」という数値でも内部的には「1022.999……」になっていることが分かったという。



 「開発チームは小数を利用した計算で誤差が起きることを加味して、誤差補正処理を追加して数式を組み立てていたので、この誤差は今回の不具合とは無関係だと考えていた。しかし別の不具合の検証時に、数式に問題があると分かった」



 青山氏が紹介したのは以下の数式だ。



f_Result = math.floor((f_FishScale + 0.0004)* 1000) / 1000



実装していた数式



 変数のf_FishScaleには、魚の大きさをミリメートルからメートルに変換した「1.022999……」のような小数が与えられる。



 そこに、0.0004を加えて三捨四入したものに1000を掛ける。その結果「1.022999……」は、「1.023399……」となる。



 これをfloat型からint型に変換することで「1023」になり、正しい魚の大きさが求められる。



 しかし、最後に1000で割った結果、「1.022999……」になった。誤差を補正しているようで、補正していない数式になってしまっていた。



 ゲーム内で魚を生成する際は、ビッグサイズやノーマルサイズなどサイズ分類をしてから魚の大きさを乱数で決定していた。しかし、この数式によって「1.023999」のように誤差補正をしないまま保存したため、「ビッグサイズの1022mm」という魚データがゲームDBに保存されていた。その後、別の不具合でサイズ分類に不整合があり、釣り老師に話し掛けたタイミングで魚の大きさからサイズ分類を行うようにした結果、今まで保存されていた「ビッグサイズの1022mm」が、「ノーマルサイズの1022mm」に正しく直されたのが不具合として扱われていた、ということだった。



 「サイズ分類処理も、魚の大きさ処理もバグを含んでいたことが分かったため、ログとゲームDBの情報から不具合が発生したユーザーに個別対応した。行動ログを基に全て対応できたので、よかった。この不具合からは、バグがある前提で不具合に対応していくべきだという教訓を得た」



 青山氏は3つの不具合と原因、改修方法を振り返り、サービス運用時の注意点について考察して講演を締めくくった。



 「今回紹介した失敗を含め、担当者が『こんな修正、影響ないだろう』と思って修正したものがサービスに影響を及ぼして起きた不具合が最も多いと感じている。リリース後の改修は要注意だ。もし、リリース後にサービスを改修するなら、改修の影響範囲を考察し、BTSに不具合内容と改修の影響範囲を記録する必要があるだろう。もちろん、影響がなかったケースもあるにはあるが、全ケースをBTSに登録するようなスタンスが求められると考えている。この教訓は、ドラゴンクエストX開発陣の結論なので、この失敗事例を知って『自分たちのサービス運用ではどうするか』を考えるきっかけになれば幸いだ」


    あなたにおすすめ

    ニュース設定