TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

Unityで将棋アプリの開発 その8(ヒントの実装)

作成している将棋アプリに、ヒント機能を実装した。

ヒントボタン(電球アイコン)を押すと、下の図のように候補手の上位3つを矢印で表示する。

f:id:TadaoYamaoka:20220305103329p:plain

複数候補手表示

下側のテキストボックスには候補手を10まで表示する(表示領域は5行までだがスクロールできる)。
テキストボックスには、勝率と読み筋も表示する。

探索がMCTSの場合、候補手が1つでも複数でも計算時間は変わらないので、短時間の探索でも複数表示できる。
これは、既にあるスマホの将棋アプリとの差別化になると思う。

なお、MCTSだと2番目の候補手の勝率が1番目より高くなることがあるが、わかりにくいのでその場合上位の手の勝率に合わせるようにして、勝率が逆転しないようにした。

リアルタイム更新

ヒントの候補手の探索にある程度時間がかかるため、プレイヤーの手番ではバックグラウンドで常に計算するようにして(探索結果は形勢グラフでも使う)、ボタンが押されたら、その時点での結果を表示し、一定間隔置きに最新に更新するようにした。
PCの将棋GUIの検討機能に近い使い勝手になる。

精度

ヒントの精度は、スマホでCPUで計算しているため、PCで最新ソフトで検討するほどにはならないが、初級者が使うには十分な精度になる。

ぴよ将棋の最高レベルのぴよ帝と対局させてみたが、ぴよ帝は1手10秒くらいかかるが、Pixel5でプレイアウト256で1手8秒くらい探索して、後手番で勝つことを確認しているので、スマホで動く将棋アプリとしては最高レベルの強さがある。

ヒントの検討では、512プレイアウトまで探索するようにしている。
途中結果を表示するので、最後まで待たなくても途中で操作できる。

実装

矢印の描画

Unityで矢印を描画するのにかなり苦労した。

Unityの標準では矢印を描画する機能はないため、やり方をネットで調べていくつか試したが綺麗な表示ができず、最終的にメッシュにテクスチャを貼る方法で実装した。

AndroidAPIで開発する場合は、drawLinesでペンとブラシを使えば簡単に実装できるが、Unityでは2Dの高度な描画APIは用意されていない。

2D向けにはスプライト機能があるが、これで任意の長さの矢印を描画しようとすると画像を引き延ばすことになるので、矢印の先端の三角の部分まで引き延ばされてしまう。

先端の三角の部分と線の部分を分けて組み合わせることもできるが、画像の透過を行っている場合、接合部分をドット単位で綺麗につなげることができないため、色が濃い部分ができてしまう。

Line Rendererを使って、矢印のアウトラインを描画して、内側にメッシュを生成して描画することを考えたが、Line Rendererはアンチエイリアシングが効かず斜めの線がギザギザになってしまうので使えなかった。

結局、メッシュにテクスチャを貼る板ポリゴンとして、矢印を描画することにした。
テクスチャにはアンチエイリアシングが効くので綺麗に描画できる。

矢印を伸ばす場合は、UV座標をそのままにして、線部分のメッシュの頂点の座標を長さに合わせて変更すればよい。
メッシュの頂点座標とUV座標は、テクスチャの矢印形の少し外側にしておくと伸縮した場合にも崩れない。

向きは、メッシュを自体を回転させることで実現できる。

矢印を引きたい2点間のx方向とy方向の差を使うと

arrow.transform.rotation = Quaternion.FromToRotation(Vector3.up, new Vector3(dx, dy, 0));

のようにして、向きを指定できる。
この際、dx=0でdyが負の場合、y軸方向にも回転してしまうため、その場合だけ、Quaternion.Euler(new Vector3(0, 0, 180))にする必要があった。

矢印のプレハブ化

矢印の表示のたびに、メッシュを動的に生成するのは処理が煩雑なため、生成したメッシュをプレハブ化した。

メッシュを生成するコードを書いて、一度実行してアセットとして保存しておき、保存したメッシュをMesh Fillerに設定して、プレハブ化すると矢印の生成のコードがシンプルになる。
一度保存したらメッシュ生成のコードはコメントアウトしておく。
アセットの保存は、以下のサイトの方法を参考にした。
Unityでメッシュをスクリプトから保存する方法 | 3DCG school

まとめ

将棋アプリにヒント機能を実装した。
矢印の描画にかなり苦労したが、メッシュにテクスチャを貼る方法で見た目のクオリティはイメージ通りすることができた。

次は、定跡機能を実装したい。