クロの制作日記

Unityでステージと障害物を自動生成しようとした話

はじめに

UnityRoomにゲーム「Hostage」を投稿しました。

ゲーム性はシンプルで、敵の戦車から隠れたり倒したりしながら人質を救出するといったゲームになっています。

動画

URL

unityroom.com

このゲームでは毎回ステージや障害物が以下の画像のようにランダム生成するようになっています。

f:id:kurora-shumpei:20210124022042j:plainf:id:kurora-shumpei:20210124022049j:plain
自動生成したステージ例

仕組みは既存の手法の組み合わせですが、頑張ったところですのでどうやったのかをこの記事で紹介しようかと思います。

ちなみにこの自動生成の方法は以下のゲームでも用いています(多少変更を加えた部分はありますが、大体は同じです)。

unityroom.com

ちなみにこれらのゲームは以下のリポジトリにて公開しています。
github.com

github.com

あと、今回紹介する自動生成の部分のコードは以下のディレクトリに保存されています。この記事の下の方にコードを直接貼っていますが、全体を確認したい場合はこちらを参考にしてください。
github.com






自動生成アルゴリズムの概要

今回使用した自動生成のアルゴリズムは①障害物の生成、②部屋の生成アルゴリズムを組み合わせたものになっており、以下のようなフローに従っています。

アルゴリズムフロー
  1. 適当なサイズのマップ(二次元配列)を作成
  2. マップの真ん中に部屋と障害物を作成
  3. 作成した部屋の壁の一つを選択
  4. 選択した壁から部屋の反対側に新たな部屋を作成できる座標を選択
  5. 選択した座標から部屋と障害物を作成
  6. 3~5を繰り返す

当初は区域分割法を用いようかなと思っていたのですが、区域分割法では通路を一緒に生成してしまうんですよね。今回制作したゲームに通路はいらなかったので、穴掘り法っぽいやり方で部屋と部屋をくっつけていく手法を実装してみました。

特に参考にした記事はないのですが、割とシンプルな方法ですので、多分、既存方法としてどこかしらに転がっていることでしょう。

このフローは以下のGenerate関数に組み込まれています。

Generate関数


障害物の生成アルゴリズム

①の障害物を生成するアルゴリズムは基本的には穴掘り法を使用しています。フローでいうと5で行っている作業ですね。

参考にした穴掘り法の記事
blog.beatdjam.com

しかし、穴掘り法をそのまま使用すると迷路が出来上がってしまうので、途中で処理を止めることでそれっぽい障害物を生成するようにしています。

あと、敵が障害物にスタックしないように障害物を作成したのと同時にwaypointも作成していますが、それはまた別の機会にお話します。

障害物生成のコード

部屋の生成アルゴリズム

②の部屋を生成するアルゴリズムは、①部屋を作成できるスペースがある座標を見つけ、②その座標を中心に部屋を作成する、というシンプルなものになっています。

フローでいうと4、5で行っている作業ですね。上手いこと部屋と部屋をつなげるための座標の検索を行っていますが、特別難しいことはやっていません。

4~5において使用する関数はそれぞれ、④SearchPos関数、⑤MakeRoom関数になっています。

SearchPos関数

MakeRoom関数




さいごに

今回はHostageにおいて使用したステージと障害物の自動生成のアルゴリズムの紹介を行いました。

このゲームは、以下の本で勉強したAIアルゴリズムを実装してみようと思って作ったのがきっかけなので、敵のAIなどもちょっと頑張って作っています。


ゲームAI技術入門 ──広大な人工知能の世界を体系的に学ぶ WEB+DB PRESS plus


ゲーム開発者のためのAI入門

次の記事ではその敵のAI周りの紹介もしようかなと思いますので、読んでいただけると幸いです。

余談

久々にUnityの記事を書いたなと思って確認してみたら、最後に書いたのが2年3ヶ月前とかだったので、もうちょっとUnityの記事を書けるように努力します...。