エディトリアルデザイナーのアプリ制作日記

Unityで遊ぶ個人開発者のメモ書き

Unityアクションゲーム制作記 その35 ランダムダンジョンの生成に挑戦してみた

 おかげさまで、なぜかGoogleのノンストップACTゲームカテゴリにフィーチャーされ、DL数が予想を超えてすごい順調に伸びている「ブラック・ブラッド・ブレイカー」β版……(てか、βでフィーチャーしてもらっていいの!?)。

f:id:hamazakifactory:20180528112511j:plain

 色々なところでクセというか、こなれてないところがあるし、まだ未実装たくさん、不親切さもたくさんあって、離脱率も凄いのですが……それでも楽しんで遊んでもらえている人がいて、感謝感激な毎日です。

 プレイした皆さんからいただくフィードバックに感謝をしつつ、のほほんと細かいアイテム作ったりしながら、Fayeちゃんをかわいくするために邁進する日々。そこそこ順調に制作が進み、割と調子づいていたある日、ふと「そーいえばランダムダンジョンって本当にできないかなぁ」と一度諦めた野望が鎌首をもたげてきたのです。

 以前は、ちゃんとゲームとして楽しめるものができる自信がなかったので、「ぼくの将来の夢」レベルで放置していたのですが、なにを思ったのか「できるんじゃね? いや、いまやっときべきじゃね?」と出所不明の自信が突然出てきたのです……。

 まぁ結果としては、予想よりも実装に時間は取られましたが、ランダム要素があるダンジョンはできました。

f:id:hamazakifactory:20180528114614j:plain

 別ワールドにせず、「迷宮」シリーズとして各ワールドの中に点在させるように設定。

f:id:hamazakifactory:20180528114713j:plain

f:id:hamazakifactory:20180528114723j:plain

 部屋・フィールドの大きさを固定にしたシンプルダンジョンです。部屋に登場する敵の種類・最後に出てくるボスはランダムです。申し訳程度に宝箱を散らすようにもしました。

 まずは簡単なものから、と一通り実装してみて思ったのが「まるっきりの無駄ではないけど、ゲームとして楽しめるものにするには、もの凄いテコ入れが必要」ということがわかりました。

問題1・やっぱり単純なマップ構成になる

 全体の大きさは固定でもいいのですが、その中にある部屋の大きさなども固定にしてしまうと、作られるマップにすぐ飽きてしまいます。作った人間としては、こんな形にもなるんだ~と面白いのですが、遊ぶ立場からみると、ゲームの面白さにはほぼ関係ない要素ですからね。

問題2・ドキドキ、ワクワクが少ない

 部屋に入ったら、適当な種類の敵が出てくるだけ。そこそこ強い奴が連続で出てくると、ドキドキしないこともないですが、部屋に入ったときのドキドキ感がほぼないのが現状です。マップ自体のギミックもないので、危機を感じるようなドキドキ感、マップをクリアしたときのワクワク感がないのは問題だよなーと痛感しました。

問題3・繰り返しプレイに耐えられない

 各所に散らした宝箱は、毎回入手できるので、小物アイテムを入手するという目的で迷宮に挑戦する意味がなくはないです。しかし、これだけでは、繰り返し挑戦する動機としては非常に弱いのは間違いありません。そこで、今回の迷宮には、装備アイテムを入手するためのイベントアイテム「小さい羽根β」を5枚集めるという挑戦するための目的を与えてみました。

 結局、最初は5枚必要にしていた羽根の数を3枚に引き下げましたけどね。理由は簡単、「だってつまんないんだもん……」。マップの生成を見守るために繰り返し遊んでいた時には、へー面白いなぁと何も考えずに繰り返し遊んでいました。しかし、必要枚数を集めるために繰り返し挑戦しなければならない、となったとたんに「作業感」を覚え、それに耐えられなかったのです。最終的には、最短で2回、おそらく5回も挑戦すればクリアできるだろうという数値の3枚に設定したのです。

 問題1・2を解消し、ダンジョンを進めていく面白さが、作業感のつまらなさを上回らないとだめなのね……よくわかりました。ちょっとへこんだけど、これをベースに面白さを乗っけていけばいいだけだ! と開き直ってランダムダンジョンに関しては、練り直します。

実装の話

 今回、ランダムダンジョンを実装するにあたってGoogle先生に聞いて、最も参考にしたのがここでした↓

wise9 › ダンジョンマップを生成するアルゴリズムの解説[投稿記事]

 正直、ランダムダンジョンを作ろうとするなら、このリンクを参考にして、その通りに実装したほうがいいです。今回自分が行ったアプローチは、こんなことをやっているバカがいる程度のやり方、わざわざ書いたのは自分への忘備録ということで……。

 さて、もともと本ゲームのマップデータ自体はCSVで管理していて、そのテキストをもとに地形パーツをシーン上に配置しています。

f:id:hamazakifactory:20180528112705j:plain

 フロア情報には、床と部屋のマーク。

f:id:hamazakifactory:20180528112717j:plain マップオブジェクト情報には、扉や宝箱、ポータルに障害物といったオブジェクト情報が書かれています。わざわざ分けたのは、一緒くたにするとなんかごちゃごちゃになって自分で管理できそうになかったため、メモリの無駄とわかりつつも2つに分けました。

 基本的には、これらの情報をプログラムで作ってやれば、ゲーム中に思うがままのマップを作ることができるようになっています。

 できる限り単純に軽く実装したかったので、部屋のサイズに関しては固定にして、大きさもそこそこに。前提条件を端折ってなるべく簡単に簡単に……。

・部屋1、交差点1枠とした4x4のブロックを持つエリアを用意

・ブロックの間には接続用の通路を入れる。

 ブロック・接続用通路・ブロック……のようにサンドイッチにする

・部屋の大きさ・通路区画の大きさは固定

・入り口は1、出口は1

・部屋どうしは必ずつながっている

 基本方針は上記のような感じです。

処理の流れ

 んで、実際にどうしていったかというと。

1)ランダムに部屋を決定

 エリア中のブロックから部屋にするものを決めます(4~8個)。

 空いているブロックは、交差点として機能させます。

 ちなみに各ブロックには、4方向にそれぞれつながっている道や部屋があるかの情報を持たせます。交差点でつながっているブロックがなければブランク(なにもない)ブロックとして処理します。

f:id:hamazakifactory:20180528123833j:plain

2)部屋どうしを通路でつなげる 

 左上からサーチしていき、部屋を見つけたらその部屋を基準に8方向調べて、調べた先に部屋があれば、部屋どうしを道でつなげます。

f:id:hamazakifactory:20180528124847j:plain

3)孤立した部屋の処理

 どこにもつながっていない部屋があったら、問答無用で近い交差点か部屋を、孤立した部屋とつなげます。

f:id:hamazakifactory:20180528124959j:plain

4)出入口を作って完成!

 最後に部屋でも交差点でもないブロックに出入口を作って完成。

 部屋でも交差点でもないブロックがなかった場合(通路と部屋で全部埋まることもあり)は、交差点に出入口を設置すればOK。

f:id:hamazakifactory:20180528125801j:plain

 ちなみに、行き止まりも作るようにすると迷路っぽくなる……らしいですが、今回は手間がかかりそうなので端折りました! ちょっと手を抜きすぎで、自動生成ダンジョンなめんなよ? と言われそうですが、もーひと工夫入れれば多少は面白くなるはず。

追記:部屋の数しだいで、出入口が生き別れる事態になることが発覚。最終的には、生成後に出入口がちゃんと繋がっているかを確認して、もしもつながっていないときには、無理やり繋げる処理を入れました。

 今後の課題としてがんばっていこう、うん。