AOYAMA Koji's プログラミングブログ - プログラミングを楽しく体験

【技術解説】ゲームのバックグラウンドリード技術でWebアプリのUX向上【自動生成☆詰将棋】プログラマー向け実装解説

2025/08/16
【技術解説】ゲームのバックグラウンドリード技術でWebアプリのUX向上【自動生成☆詰将棋】

 自動生成☆詰将棋Webアプリでは、 ゲームで使用されているバックグラウンドリード(BGリード・裏読み)の技術を用いて、 ユーザー体験(UX)を向上させました。 色々な場面に応用できますので、その詳細を解説します。
 なお自動生成☆詰将棋Webアプリは、この記事などでお楽しみください。

プログラミングブログ記事一覧



[PR]

課題:待ち時間が発生してしまう


 自動生成☆詰将棋は、ある程度完成して検証できるようになったばかりのころは、待ち時間が気になる状態でした。

問題生成には時間がかかる


 自動生成☆詰将棋Webアプリの問題生成は、ユーザーが操作している端末で実行します。 マシンスペックにもよりますが、数秒程度かかります。
 つまり何も工夫しない場合、更新ボタンを押下してからお待ちいただく時間が数秒です。

ユーザー体験への影響


 数秒間待つことは、低頻度であれば大きな問題ではないかもしれません。
 しかしながら繰り返しプレイしてもらう自動生成☆詰将棋の性質上、毎回数秒かかりますと、ストレスを感じさせてしまうでしょう。
 可能なら、ユーザー(=お客様)をお待たせしない設計にすべきです。

ユーザー(=お客様)を待たせない設計


【技術解説】ゲームのバックグラウンドリード技術でWebアプリのUX向上【自動生成☆詰将棋】 マルチスレッドを用いたバックグラウンド処理で問題を生成しプール  結論から書きますと、マルチスレッドを用いたバックグラウンド処理で、 問題をプールし、待ち時間を短縮しています。

ゲームのバックグラウンドリードを応用


 より具体的には、ゲーム業界で使用されているバックグラウンドリードの技術を用いて、 裏、すなわちメインスレッドとは別のスレッドで問題を生成し、プールしておく設計にしました。

プールされた問題を取り出して更新


 問題更新ボタンが押下されたら、既にプールされている問題からひとつ取り出し、盤面に表示します。
 並行してバックグラウンド処理でさらに問題を生成して補充します。 常に数個の問題をプールしておくようにします。

ゲーム業界で用いられるバックグラウンドリードとは


【技術解説】ゲームのバックグラウンドリード技術でWebアプリのUX向上【自動生成☆詰将棋】 業務業界におけるバックグラウンドリード
 ゲーム業界におけるバックグラウンドリードは、図の左のシームレス移動で用いられる技術です。

ストレージからメモリーへ読み込んで描画


 ゲームの各シーンの情報は、ストレージにあります。
 ゲームプレイ中は、その中から必要なぶんだけメモリーに読み込み、描画可能な情報に変換して描画します。
 メモリーは高速ですが容量が少なく、ストレージは大容量ですが低速です。 PlayStation 5 など最新ゲームマシンは、ストレージが SSD になり、だいぶ高速になりましたが、 それでもメモリーに比べれば遅いです。
 そのため、このストレージからメモリーへの読み込み処理をいかにうまく実施するかが、シーン切り替えの重要な要素のひとつになります。

次のシーンを先読みしてシームレス切り替え


 上図の左は、街を移動している間に、街の外の森の情報をバックグラウンドリード、すなわち裏の処理で先読みして、描画可能な情報に変換します。
 準備が終わったら扉を空けられるようにする等の工夫で、ユーザーに読み込んでいることおよび待ち時間を感じさせずに、シームレスなシーン切り替えが可能になります。
 ただし、バックグラウンドリードをするためには、メモリーが倍必要ですし、処理も複雑になります。 特に古いゲーム機では、メモリーがボトルネックで、バックグラウンドリードをしている余裕はありませんでした。

切替時に読み込むマップチェンジ


 バックグラウンドリードをしない場合は、上図の右のように、シーン切替時に暗転等させて、その間にすべて読み替えで、シーンを切り替えます。 この間は、ユーザーを待たせることになります。
[PR]

バックグラウンド処理での問題生成の実装


 前述のゲーム業界におけるバックグラウンドリードの技術を用いて、自動生成☆詰将棋の問題生成を、バックグラウンド処理で行います。

問題生成処理の基本的な実装


【技術解説】ゲームのバックグラウンドリード技術でWebアプリのUX向上【自動生成☆詰将棋】 バックグラウンド処理での問題生成
 自動生成☆詰将棋の問題生成では「ランダムに駒を配置し、詰み手順を探索する」という処理を、指定手数で詰む形が発見できるまで繰り返し実行します。
 このうち処理負荷が高いのは、詰手順探索です。
 問題生成をバックグラウンド処理にする際には、 この「詰手順探索」を別スレッドで行うことで、 比較的シンプルな設計を保ちつつ、 メインスレッドを邪魔しない設計・実装としています。

JavaScript の Web Worker


 当ブログを含めたWebページの実装に用いられる JavaScript は、 原則シングルスレッドの言語ですが、 Web Worker という、別スレッド機能も用意されています。
new Worker( '../js/shogi/sgAI.mjs' , { type : 'module' } );

 こうすることで、 sgAI.mjs という詰手順探索の主要部分を担う JavaScriptモジュールを、別スレッドで動作させることができます。

Web Workerを用いたマルチスレッド


 Web Worker を用いることで、JavaScript をマルチスレッドで動作させることができます。
 ただしC++等のスレッドと異なり、Web Workerはメモリー空間が原則として独立しているため、マルチスレッド特有の共有メモリーの排他処理に悩まされることがありません。 一方で、データの受け渡しには工夫が必要です。
 実際には C++ のような使い方も用意されていますので、詳しくは Web Worker などのキーワードで調べてみてください。

メインスレッドをブロックしない意義


 詰手順探索という負荷の高い処理を別スレッドに分離することで、メインスレッドがブロックされることはなくなります。
 逆に、もしメインスレッドで重い処理を行うと、他の処理はその重い処理の終了を待ってから順番に実行されます。
 主にメインスレッドでは、ユーザーとのインタラクティブな処理が実行されます。
 例えば自動生成☆詰将棋では、駒を操作して動かす際の「徐々に目標マスに近づける」描画も、メインスレッドの処理です。 30分の1秒ごとに、座標を少しずつ変更して描画することで実現しています。
 つまりそれより長い時間処理がブロックされると、動きが止まったり、カクカク動くことになります。
 しかし重い処理を別スレッドで行うことで、処理を邪魔されることなくスムーズな駒の移動が実現できます。

問題の並列生成の実装


 自動生成☆詰将棋における実装では、バックグラウンド問題を生成する処理は、メインスレッドで、その管理を行います。
 ランダムに駒を配置する処理もメインスレッドで行い、詰手順探索を Web Worker に託して、メインスレッドの処理はひとまず完了します。
 そして Web Worker の処理が完了したイベント発火をメインスレッドで受けて、その結果に応じた処理を行います。
 この問題生成のメインスレッドの処理を2つ順番に動かすことで、バックグラウンドで2つの問題を並行して生成することができます。
 メインスレッドではそれぞれの進捗を確認する処理もあり、問題が早く完成した方から先にプールし、使用しています。

詰手順探索の別スレッド処理化の工夫


 前述の処理を実現するために、詰手順探索を、別スレッドで処理するよう実装します。 そのために工夫したことがありますので、各設計についてご紹介します。

並列処理するための設計


 詰手順探索は再帰定義での呼び出しを基本としつつ、処理が重いためさらなる並列処理もできるように設計しています。 具体的には、引数のみで入力を完結させており、また、結論が出たときに出力できるようにしています。

引数のみで入力完結

 関数の引数のみで入力を完結させることで、その関数ローカルですべて処理できるようになります。
 その関数は、再帰定義で呼ばれても、別スレッドから呼ばれても、正しく処理できます。

探索結果をマージ

【技術解説】ゲームのバックグラウンドリード技術でWebアプリのUX向上【自動生成☆詰将棋】 並列処理の探索結果をマージ  再帰定義での関数呼び出しであれば、すべての結果が再帰呼び出し先から戻ってきます。
 しかし並列処理の場合、その返り値では探索結果がわからず、また、いつ結果が出るかもわかりません。 バラバラのタイミングで、部分的な結果が出ます。
 そこで、共有場所にバッファを用意しておき、探索結果が出る度にマージすることで、 いつ結論が出ても問題ない設計にしています。

オーバーヘッド削減のためのモジュール設計


 JavaScript の Web Worker は、スレッドが生成される度にモジュールを読み込むことになります。 もし、そのモジュールの中から import されるモジュールがあると、さらに読み込まれ、オーバーヘッドが大きくなります。
 そのため、Web Worker として実行されるモジュール内からの import をしない設計としました。 具体的には以下の通りです。
  • Web Worker モジュールは sgAI.mjs
  • sgAI.mjs からは他のモジュールを import しない
  • 共通定義は sgAI.mjs に記載し必要なモジュールから sgAI.mjs を import する

 これにより、オーバーヘッドを最小限にとどめて、より柔軟に Web Worker を活用できます。

ユーザー体験改善効果


【技術解説】ゲームのバックグラウンドリード技術でWebアプリのUX向上【自動生成☆詰将棋】 バックグラウンド処理での問題生成
 この処理を入れる前は、問題更新ボタンを押下してから、問題が表示されるまで、数秒かかっていました。
 バックグラウンド処理で問題生成したプールから取り出す方式にしてからは、 待ち時間は感じなくなりました。

体感待ち時間ゼロ


 一般的なユーザーが問題を解いて解答を確認するまでには、最低でも数秒から数十秒はかかります。 この時間内にバックグラウンドで次の問題生成は完了するので、更新ボタンを押下して際の待ち時間はありません。 体感する待ち時間はほぼゼロです。
 もし、画面に表示された問題を解くスピードが、将棋のプロ棋士並みに早い場合は、バックグラウンド処理の生成が追いつきませんが、 それは対象ユーザー層から外れますので、問題ありません。

技術を感じさせない技術


 本技術を導入することで、詰将棋問題の自動生成で実施している膨大な処理を、ユーザー(=お客様)は感じることなく遊べます。
 自分の技術力を誇示したい技術者としては残念に思うところもありますが、ゲームやユーザー体験の世界では、使用している技術を感じさせない技術こそが最高の技術力だと、筆者は考えています。
[PR]

まとめ


 ゲーム業界におけるバックグラウンドリードの知見を、Webアプリケーションに活かし、バックグラウンド処理で問題を生成しプールする技術について解説しました。
 Web Worker の起動コストを考慮したモジュール設計、メインスレッドと Web Worker のスレッドの使い分けなど、実装に関する紹介もしています。
 ゲームでは、ユーザーとのインタラクティブ性が重要視されます。 そこで一般的に使われている技術が、Webを含む各種アプリケーションでは使われていないことがあり、導入することでユーザー体験向上の一助になることは少なくないでしょう。
 本記事はその例のひとつです。 別スレッドで処理する必要があり、実装は大変ですが、こうした丁寧な対応がユーザー体験を向上させます。 少しでも皆さまの実装の参考になりましたら幸いです。

補足

  • 記事の校正/添削に生成AIの Anthropic Claude を利用しております。
  • 記事内の画像の作成に生成AIの OpenAI ChatGPT を利用しております。
  • 画像内のラスタライズ文字フォントにOpen Font LicenseNoto Sans Japaneseを使用しております。

カテゴリー:自動生成☆詰将棋,プログラミング解説
[PR]