【Unityで作ろう!ゲームアルゴリズム】シミュレーションゲームのアルゴリズムを作ってみる
cover
【Unityで作ろう!ゲームアルゴリズム】シミュレーションゲームのアルゴリズムを作ってみる
賀好 昭仁
2017.08.29

2017年5月、Unityの一大イベントであるUniteが開催されました。 Unity2017に関する魅力的な機能も色々発表され、期待に胸が膨らんじゃいます。

そういえば、今回のUniteには会社の後輩がボランティアスタッフとして参加しました。 「大変だったけどとっても楽しかった!」とのことですので、予定が確保できそうな方はぜひ次回のUniteに参加してみてください!(筆者も参加してみたい・・・!)

さてさて、今回はシミュレーションゲームのアルゴリズムを作ってみましょう。(賀好 昭仁)

シミュレーションゲームというジャンルは広すぎました

改めて調べてみると、シミュレーションゲームには

・シミュレーションRPG ・恋愛シミュレーション ・フライトシミュレータ

など多種多様なゲームが含まれております。

ということで、今回はシミュレーションゲームの中でも特に歴史のある「マス目を使ったターン制戦略シミュレーションゲーム」のアルゴリズムを作ってみます。

※「マス目を使ったターン制戦略シミュレーションゲーム」ですとちょっと長いので、以降は「戦略シミュレーション」と称させていただきます。

<余談> 最近、ファイアーエムブレムヒーローズ(FEH)で久々にシミュレーションRPGをプレイしました。 筆者はこれまでシミュレーションRPGをいろいろプレイしてきましたが、すべて1マップに1時間前後かかるガッツリ系のゲームばかりでした。 FEHもその類かと思いきや、1マップ数分で終わるというスマホゲームらしいライトさ。 本格シミュレーションPRGでも工夫次第でここまでライトに作れるものなのか、と驚いたものです。(そして、ライトでも面白い・・・!)

戦略シミュレーションの要素を考えてみる

ゲームを作っていくにあたって、まずは戦略シミュレーションの要素を考えてみましょう。

戦略と名がつく通り、自軍のユニットを使って敵軍のユニットと戦うゲームですので、

・自軍ユニット ・敵軍ユニット

は必須です。

そして、戦うための舞台も必要です。 障害物の無い平原、うっそうとした森、山岳地帯など、さまざまなマップが登場すると楽しそうですね。

戦略シミュレーションに最低限必要な要素はこれくらいでしょうか。要素はとっても少ないですが、ユニットの種類・マップの種類・自軍と敵軍の戦力バランスや戦況・敵AIなどに変化をつければ、要素は少なくてもさまざまな楽しみ方ができます。

そういえば、将棋やチェスなどはユニットの種類が固定でマップも1種類しかありません。 それでも打ち手次第でさまざまな局面が楽しめることを考えますと、戦略シミュレーションの根本的な部分の奥深さが垣間見えますね。

ユニットの動ける範囲を考えてみる

いざ戦略シミュレーションを作ろうとしたとき、まず頭を悩ませるのは「ユニットが動ける範囲をどう計算するか」だと思います。

将棋やチェスでは各コマの移動のルールがシンプルなため、動ける範囲を求めるのは簡単です。 ただ、戦略シミュレーションではユニットの移動力に応じて1回の行動で複数マス動けたり、同じ1マスでも平原と森で移動コストが変わったりと、さまざまな要素が絡んできます。

これらを解決するために、移動可能範囲を計算するためのアルゴリズムを実装する必要があります。

移動可能範囲を求める

移動可能範囲は、簡単なアルゴリズムで求めることができます。まずはマップの各マス目の移動コストを列挙します。 移動不可のマス目は、どのユニットも移動不可能になるような大きな値を入れておけばOKです。 下の図では、移動コスト1の茶色のマスは平原、移動コスト2の緑色のマスは森、移動コスト9の灰色のマスは岩山(進入不可)と考えてください。

image
図 1 マップの移動コスト

続いて、移動力の計算を行います。まずは動かしたいユニットが居るマスの座標に、そのユニットの移動力分の数値を入れておきます。下図は移動力4を持つユニットがマップ中央にいた場合の例です。

image
図 2 移動力の初期値

続いて、ユニットの居る上下左右のマスに、対象マスの移動コスト分を引いた値を入れます。 ※対象マスに既に値が入っていた場合、上書きせずそのままにします。

下図では、ユニットの居る赤いマスを基準に、その四方のマス(黄色いマス)に値を入れています。 右側のマスは森(移動コスト2)なので、ここだけ数値が2になっています。

image
図 3 移動力の計算1回目

続いて、移動力の値を1減らしたマス、つまり値が「3」のマスを基準に同じ計算を行います。

image
図 4 移動力の計算2回目

あとは値を1ずつ減らしていき、0になるまで同じ処理を繰り返せば、移動可能範囲を導き出すことができます。 ちなみに、値がマイナスになったマスは移動力が足りず移動できないマスですので、最終的な移動可能範囲は下図の青いマスとなります。

image
図 5 移動可能範囲

特殊なマス(後述)がない限り、移動力や地系が変わっても同じ処理で移動範囲を求めることができます。

シミュレーションPRGや戦略シミュレーション全般で大活躍しそうなアルゴリズムですね!

移動先から経路を求める

ユニットを移動させる際にユニットが移動先にパッとワープしたり、移動不可マスを通って移動したりすると、プレイヤーは違和感を感じてしまいます。 違和感を感じさせないようにするためには、目的地までの移動経路を算出する必要があります。

移動経路は、先ほどの移動範囲の計算と逆の手順で導き出すことが可能です。

下図は赤いマスが移動先だった場合の例です。 まずは移動先マスの値(残りの移動力)に、そのマスの移動コストを足します。 四方にあるマスを見ると、上記の値に合致するマスが必ず1つ以上存在します。(図中の黄色いマス) ユニットはこの黄色いマスを通って移動したことになります。 続いて黄色いマスを基点に同じ処理を繰り返すことで、徐々に移動経路が明らかになっていきます。

image
図 6 経路算出(移動先から2歩手前まで)

もし黄色いマスが複数存在する場合は「どちらからでも来られる」ことになります。

image
図 7 経路が複数ある場合

あとはユニットが元居た位置までこれを繰り返せば、移動経路が明らかになります。下図では、中央にある「4」のマスから「←↓←←」の経路と「↓←←←」の経路の2パターンが割り出せました。

image
図 8 完成した経路

アルゴリズムの注意点と改良方法

今回は不要ですが、もしもマップに下記のようなマスが存在する場合は前述のアルゴリズムをそのまま使うことができません。

・移動力を消費しないマス ・通ると移動力が回復するマス

このようなマスに対応する場合、下記のような処理を加える必要があります。

・該当マスから周りのマスに対し、移動力の計算&書き込みが終わったかどうかのフラグを設ける ・数字(残りの移動力)が埋まっているマスに対して、より大きい値が入れられる場合は値を上書き、上記フラグをクリアする処理 ・ひと通りの計算が終わったのち、マス目上の最大移動力をベースに再度同じ計算を行う(この際、上記フラグが立っているマスは計算対象から除外)、全てのマスにフラグが立つまで何周も続ける

また、移動力回復マスにワープするマスを組み合わせると無限ループに陥る可能性もありますので、このようなマスを実装する場合は注意しましょう。

動かしてみる

今回のサンプルプロジェクトはこちら。

https://github.com/akako/gamealgorithm-war-simulation/releases/tag/for_algorithm10

ユニットを選択して移動可能マスをハイライト、マスを選択して経路計算+移動するところまでを作りました。 まだまだゲームとは言えませんが、これだけでも戦略シミュレーションの香りがプンプン漂ってきますね。

まとめ

今回のアルゴリズムは、マス目を使った戦略シミュレーションであれば必ず活躍します。 HEX(6角形)のマス目でも同じアルゴリズムが適用できますので、ぜひ試してみてください!

ライター

賀好 昭仁
qnoteスマホアプリ開発チーム技術主任。PHP・Android・iOS・Unityなど複数のプラットフォームでの開発を行う。 しばしば7匹の先輩猫社員たちにイスを占領される。
賀好 昭仁の記事一覧を見る
気になる人のXをフォローしよう!
アンドエンジニア公式LINEでは
新着記事やエンジニアに役立つ情報をお届け!
日々のキャッチアップをお手伝いします!
この記事をシェア
マイナビITエージェント

編集部オススメコンテンツ

Sponsored
【無料個別転職相談会】アプリケーションエンジニア向け!リモート・在宅勤務で働きたい方へ
マイナビITエージェント
Sponsored

アンドエンジニアへの取材依頼、情報提供などはこちらから

お問い合わせ・情報提供
はじめて転職される方へ
SE・システムエンジニア(IT/通信/インターネット) 求人一覧

編集部おすすめコンテンツ

Sponsored
【無料個別転職相談会】アプリケーションエンジニア向け!リモート・在宅勤務で働きたい方へ
マイナビITエージェント
Sponsored

アンドエンジニアへの取材依頼、情報提供などはこちらから

Powered by マイナビ AGENT