Unityアクションゲーム制作記 その17 基本操作のおさらいと調整
めずらしく更新が早いですが、今回は復習ネタが多めでいきます。
さて、これまでさらしている動画を見ていただければわかるのですが、今回作っているゲームの操作にはバーチャルパッドを使っています。導入する際の方針としては以下の2つがありました。
- どこを押しても対応できるようにする
- いわゆるボタンは使わない
どこを押しても大丈夫というのは、ユーザーがプレイする時にベストポジションで遊べるようにしたかったということもありますが、縦・横どちらでも遊べるようにしたかったのが大きいです。特に縦持ちにした時には、横にUIを置くスペースが限られる(というか置けない)ですからね。
ボタンを実装しない理由は簡単で「自分の手では、ちゃんと狙って押せない!」から。幾つかそういったタイプのゲームもやってみたのですが、すぐに押す場所がずれてしまいストレスの溜まること溜まること。
どこまでできるかどうか全くわからないまま、「1タップのみの操作でどこまでできるか」この点だけは最初から決めていたのですが……結果、くそ面倒なことになりましたが……(自業自得)。
まず「1タップ」でできることいえば、画面を「押す」「離す」これだけ。あとは、押している時間、離している時間、移動距離との組み合わせで、操作のバリエーションを作るしかありません。キャラクターの移動に関しては、上の写真にある通り、最初にタップした場所からスライドさせた方向へ、キャラクターを移動するようにしてあります。操作としては「押しっぱなし+移動」ですね。
攻撃自体は、タップ=「押して離す」動作で実現しています。連打することで攻撃がつながるものと、特定タイミングでタップすることでつながる連続攻撃の2つを用意していますが、当然のことながら、1タップでは移動しながら攻撃するという操作ができません。そこで攻撃している最中に、敵を少しだけ追尾するようにしています。
今のところは、連続攻撃の初弾で攻撃した敵の中からプレイヤーキャラに一番近い敵をターゲッティング。以後、連続攻撃を繰り出すたびにそのキャラをちょっとだけ追尾するようにしてあります。そして連続攻撃が途切れたら、次の攻撃時に新たなターゲットを探すという具合です(黄色の1〜3)。攻撃を繰り出すたび、「常にプレイヤーに近い敵を叩いていく=敵全体に平均的にダメージを与えていく」のもありなのですが、今回は「1匹を追尾してとにかく敵の数を潰し、プレイヤーへの脅威を減らす」ことを優先としました。
しかし、もう一つ困ったことがあって、それはプレイヤーが倒したい敵の優先順位をどうやって知ればいいのかが、現段階では知る術がないということによるものです。特にボス戦。なによりボスが重要なターゲットであり、倒すべき敵として優先度の高いものです。しかし、時にはボスが召喚した雑魚を先に片付けたい状況というのも発生することもあるので、一概にボスまっしぐらが正しい状況とは言えないのが悩ましいところ。青の1〜2の順で攻撃するか、それとも黄色の1〜3で攻撃するか……勝手に判断してやってくれるようにするにはどうすればいいのか……。脅威判定って、自分の攻撃力と敵のHPの兼ね合いで判断できるのかなぁ……とか思いを巡らせたこともあるのですが、「いまはその時ではない=そこまでやってらんねーな」とさっくり投げ出してあります。悩みどころですが、現状で致命的な問題となっていないので、今後の課題とします(=おそらく放置したままなパターン)。
んで、ようやく今回調整した部分。最近、操作としてフリック操作による、ダッシュ移動を実装しました。操作としては「押す(ごく短い時間)+移動(そこそこ大きく)」で、緊急回避用として用意しました。実装したのは、フリックした方向に一定距離ダッシュ移動するというごく基本的なものです。
多数の敵に囲まれた状況から脱出するための操作としては、立派に役割を果たしました。操作を覚えることでスピーディーな戦闘が楽しめるようになった……んですが、遊んでいくうちにどうにも「なーんか物足りねぇなあ」と思うように。ダッシュ移動は気持ちいいのですが、そのあとに敵を叩くためにえっちらおっちら移動しなければならない展開がちょっとだるい。まぁ、ダッシュ移動そのものが敵から離れることを第一目的としているんだから当たり前です。でもでも、もーちょっとアクティブにダッシュ移動を使えないかなーと欲張ってみたい、要は、攻撃する時に敵を追尾したように、ダッシュ移動をしたときもいい感じで、敵を追尾できないかなーということです。
まずやってみたのは、ダッシュ操作直後に敵を追尾し始めること。回避するという概念はどこへやら、ただ単に敵まっしぐらになってしまうのでNG。しかたなく、ダッシュ移動そのものをじっくりと見直してみることに。
今回のダッシュ移動は、一定速度で高速に移動する期間とそこから次第に減速していくというシーケンスで実現していました。そこで、高速に移動しているときはそのままにして、減速していくときに敵を追尾させていけばいい感じにならない? とやってみたところ、そこそこ思い通りに敵の後方へ回り込むような軌道が実現できました。
やったーと喜んでいたのですが、問題はすぐに発生。次なる問題は、追尾する敵をどう選べばいいか? です。脅威度判定は今後の課題ということで、追尾する敵を選ぶ基準は、いまのところ距離だけ。なので、移動しているどこのポイントから、敵を選ぶだけになります。タイミングとしては、
- ダッシュ開始時
- ダッシュ移動終了時
- ダッシュ+減速終了時(ダッシュ完了後)
くらい。まぁ結論から言うと、ダッシュ開始時にダッシュ完了後の最終到達地点の座標を計算(直線移動なので楽ちん)、そこから一定の範囲にいる敵を探してターゲッティングするという方法に落ち着きました。
こうすることで、敵のいない方向へダッシュ移動すれば確実に敵から離れられます。ダッシュ移動の距離を把握している必要はありますが、覚えてしまえばダッシュ移動して敵との距離を素早く詰めることも可能になりました。めでたしめでたし……。
とはいかないのが現実。先ほどからちょくちょく出てきている敵の脅威判定をちゃんとやってないので、現状では、ダッシュ移動後にとりあえず手近な敵にまっしぐらしてしまいます。つまり、プレイヤーの思惑と外れた場所へ突っ込む可能性も高いということですね。プレイヤーは、ゲームに慣れてくればくるほど、先読みというか戦闘状況の先を見て戦うようになります。つまり、こういったアシスト機能が、プレイヤーが描いている戦略と変わってくると、結構なストレスを感じてしまうんですよねぇ。わかっていても解決策は浮かばず……。
しっかし、最近は問題を解決するどころか課題だけが積み上がってきて、ゲームが出来上がる気がしなくなってきてるけど、気のせいだろうか……。まぁ引き続きがんばっていこう、うん。
Unityアクションゲーム制作記 その16 ボスらしい動きをするロジックを組み込む
ようやく懸案となっていたボスの挙動の目処が、ある程度立ちました。本当は昨年内に終わらすつもりだったもの……ここまで引っ張ってしまった原因として、ゲームとして盛り込んだアクションのシステムにありました(要は根幹に関わる部分)。
まず、今回制作しているアクションゲームは、1対多の戦闘がメインになっています。敵の数が多いということは、それだけプレイヤーが囲まれることも多くなり、下手をするとすぐ多数の敵にボコボコにされてしまう危険があります。そうなるとプレイヤーは、敵からボコられないために集団から離れて攻撃をする、ヒットアウェイ戦法を選択し、チクチクと戦うことに……これではゲームとして爽快感に欠けてしまいます。
せっかく多くの敵と戦っているのだから、バッタバッタと敵をなぎ倒すような、より気持ちいい戦闘にするにはどうしたらいいんだろう? そこでひねり出したのが、攻撃を受けた相手の動きを封じるようなリアクションをさせるというものでした。
今回用意したのは、以下の4つ(プレイヤー・敵ともに設定可能)。
- ノーマル:ダメージのみを与える
- ブロウ:相手を一瞬ひるませる(相手の攻撃をキャンセルする)
- ノックバック:相手を一定距離吹き飛ばす(相手の攻撃をキャンセルする)
- ブラックアウト(気絶):一定時間、行動不能状態にする
基本的にプレイヤーが連続攻撃を使った際には、初弾(ノーマル)>二段目(ブロウ)>三段目(ブロウ)>フィニッシュ技(ノックバックなど)と設定してあります。初弾をノーマルにしたのは、さすがに出合頭で敵の攻撃をつぶせてしまうと、本当に一方的な無双状態になってしまうので、ここは敵にも反撃できる余地を残してあります。結果として、プレイヤーが積極的に攻めることで敵の動きを封殺でき、いい感じの無双アクションを楽しめるようになったかな? という具合です。攻撃の間合いが違ったり、遠距離攻撃をしてくる敵などバリエーションを用意して、いっぺんに登場させれば、それなりに緊張感のある戦闘バランスになっていたりしました。
ただし、ボス戦のときに問題が起きました。雑魚の場合は、数の暴力でプレイヤーへの反撃の余地はあったのですが、ボス単体とのサシ勝負では、ブロウによって攻撃がつぶせることが仇になってしまったのです。極端な話、あまりに簡単に敵の攻撃がつぶせてしまうので、ボスを一方的に殴るだけで戦闘が終わってしまうということも……結果、ボス戦がすげーつまらないものになってしまったのです。ボスの行動自体、雑魚と同じくプレイヤーとの状況(攻撃されたとか、見つけたとか)などに応じて、幾つかの行動を選択し、ループさせているだけなのも原因の一つだったといえます。
じゃあ、ボスでは「ブロウ」を無効化すりゃーいいじゃん? 対プレイヤー用にロジックを組み直せばいいじゃん? と思わなくもないのですが、単に「ブロウは無効」としてしまうだけでは、あまりにゲーム的な都合が見え見えになってしまいますし、ボスごとにロジックを組むのは、ボスを量産する際にかなりきつそう……。
そんな感じで、攻撃し続けていると、いい感じに敵が判断して回避して反撃したりできないかと、ここ数ヶ月ず〜〜〜〜っと頭を悩ませていたのです。まぁ、プレイヤーに対するリアクションを逐一判定し、対応する反撃方法を組み込んでやるのが王道なんでしょう、きっと。ただ、ロジックそのものを組み込んでしまうと、どういう反撃をしてくるのかすぐプレイヤーにバレるだろうし、後々、敵の強さを調整したいときにすげーめんどくさそうだったので、ない知恵絞ってうだうだと考え込むことに。どーしよっかなーと、どうすればいいかなーと悩み続けたのですが、結局やりたいことは、
- 状況が悪化したら、有利な状況に変化するように自律的に行動してほしい
これに尽きます。これができれば、ボスとの戦闘も駆け引きのあるものになるはず! そして、状況が悪化するということは、敵にとって不利な状況に追い込まれることにほかなりません。今回のゲームで敵にとって不利な状況とは、
- 壁際に追い詰められる
- プレイヤーからダメージを受け続ける
単純化すれば、この2つに集約されるかなーと。そしてこの2つそれぞれにストレス値を用意して、敵にとって不利な状況を明確に数値化することにしました。
- 壁際に追い詰められる = 地形ストレス上昇
- プレイヤーからダメージを受け続ける = 攻撃ストレス上昇
ボスが壁に近づけば近づくほど=プレイヤーに追い詰められる=地形ストレスは上がる。プレイヤーから攻撃を受ければ受けるほど攻撃ストレスは上がっていく。それぞれがある一定のしきい値を超えた時に、ボスへ回避や反撃する行動を起こさせるという具合です。
しかし、これだけでは地形・攻撃ストレスで2パターンしかバリエーションを作れません。そこでさらにストレスレベルを用意して、そのストレスレベルに応じて回避や反撃行動を設定できることにしました。ストレスレベルはひとまず5段階。ストレスレベルが上がる条件は、ストレス値がしきい値を超えた時で、ストレスレベル下がる条件は時間経過のみとしました。かなり単純な仕組みですが、しきい値(レベルに関係なく固定)とストレスレベルを下げる時間(レベルごとに設定)をうまく調整することで、敵の攻撃をより激しくできたり、いったんレベルが上がってしまったら下がりにくくしたりできるので、これによってボスの個性も出せるようになっています。
さらに、ボスに対して有効な攻撃をするプレイヤーに対しては、常にストレスレベルが高くキープされ、激しい反撃を多くするようになり、アクションが苦手なプレイヤーに対してはストレスレベルの上昇が抑えられるといった、難易度調整も自動でできるようになりました。
結局のところ、ボス固有の攻撃のバリエーションを考えなきゃいけないし、各種数値の設定もちゃんとしないといけないしで、今回の方法でボスの制作が楽になったわけではありません。とはいえ、ある程度の共通な仕組みでボスの量産ができそうな感じになってきました。あとはちゃんと忘れずにドキュメントを整理するだけ……なんですけど、めんどーなことはいつも後回し。これまでも、メモとしていろいろ書き残しているのですが、たまーに間違ったコマンドとか変更前の仕様とか書いてあったりして、油断がなりません(常に過去の自分と戦っている…)。
とはいえ、大きな問題が一つ片付いて一安心。次は、テストプレイしていう間にず〜っと気になっていたダッシュとチャージの使い勝手の悪さ(=操作性の悪さ)を、少しでも良くしなければ……そろそろちゃんと考えなきゃいけないゲームそのもののデザインとともに悩むとします。がんばろっと。
Unityアクションゲーム制作記 その15 オープニングを作る
さて、ゲーム本体のシステムも作り終えないうちに、どうにも煮詰まってしまって気分転換にオープニング映像を作り始めてしまいました。 とはいえ、映像制作なんて、Live2D Creative Award 2016用に応募用に作ったくらい。どう手をつけようかなーと悩みましたが、まずは「なにをやりたいか」を明確にして、映像のイメージを膨らます作業から始めました。
1)音楽との連動
目指すはBGMとの完全同期……なんてことは、これっぽっちも思わず、要所要所でカットの切り替えをしたりして「なんとなくそれっぽい」風に見えればいいやー、ということを目標にしました。
2)アングルとカメラワークを可能な限り単調にしない
使おうとしていたBGMが約80秒で、ちょうどテレビアニメのオープニングくらいのサイズ。個人的にもよくアニメは見るので、記憶にあるいい感じのオープニングを思い出しつつ、アクションゲームらしい見せ方にこだわる方針に。
3)UnityエディタとDOTweenとTypeface Animaterと少々のスクリプトでなんとかする
こういった映像を作るためには、それ専用のタイムラインエディタを使うのが筋です。しかし、ツールを覚えるのも面倒だし、80秒くらいならTween系でなんとかなるだろうということで、Unity エディタのシーン上にオブジェクトをぽちぽち置き、カメラやオブジェクトの制御はDOTweenとスクリプト、クレジットなどの文字の演出はTypeface Animaterでゴリゴリ作っていきました。
まぁ、「とりあえずやってみよう! 無理だったらちゃんとツールなり導入する」という、いつも通りの見切り発車スタートってことです。
・まずは絵コンテを作る
映像制作に慣れているプロならともかく、どう見せたいかもわからない素人がツールも使わずにやるわけですから、それなりに作りたいものをきっちり書き出しておく必要があります。要するに絵コンテというやつですね。その試行錯誤の結果がコレ↓
音楽と映像の流れをそれっぽくということで、フリーのサウンド編集ソフトであるAudacityで表示される曲の波形を縦軸(時間)にして、時間ごとにどのようなカットを再生するかをゴリゴリと記入していく超アナログスタイル。前半はプレイキャラのFayeとアクションをじっくり見せ、後半にゲームの魅力となる敵とのアクションをモリモリと入れ込んで行こうという方針にしました。
ちなみに使用ツールは、illustrator(笑)。仕事で使い慣れているので、手で書くよりはいろいろ楽かなーというだけの理由です。
・Unityエディタに落とし込む
ここからは力技。絵コンテに書かれたカットごとに見せるオブジェクト、カメラ、ライト、キャンバスを作ってシーン上に配置していきます。再生時には、指定された時間に再生したいカットの親オブジェクトをアクティブにしていくだけ。もちろん、カットごとに使い回せるモデルやカメラ、ライトを置くのは、はっきり言ってメモリの無駄です。しかーし、今回はそういう細かい事(?)は気にせず突っ走ることにしました。
ちなみにモデルで使っているシェーダーは、標準のUnityChanシェーダーです。ただ、単色のイメージにするため、テクスチャをグレースケールにしてあります。この状態で、カメラのBackGroundとDirectionLightのカラーを一緒にすると、今回のようなイメージになります。
ただ、目だけはオリジナルのモデルの色を残したかったので、目のメッシュだけに当たるように専用のライトを用意して、体に当たる色とは別になるようにしてあります。
・コンポーネント(制御スクリプト)
ここも単純に、移動する、アニメーションを再生するといった、単機能のものを対象のオブジェクトにペタペタ貼り付けていくスタイルでごり押し。例えば、カット再生開始後にwaitTimeだけ待ってからアニメーションさせたい場合は↓のようなスクリプトを対象オブジェクトへ貼り付けます。
ちなみに同カット内で連続的にアニメーション再生させたいときには、もう1つくっつけて、開始時間と再生アニメーションの名前を入れていく……。
……バカですねぇ。それでも、前半まではオブジェクトの数も少なく、複雑なカメラワークもなかったので良かったのですが、後半のバトルシーン的なものを作りたくなってからは地獄でした;; とはいえ、半分まで作ってしまったものですから仕方ない。後半も泣きながら突っ走りましたヨ。
・結論 ちゃんとしたツールを使おうぜ!
クオリティはとにかく、なんとか無理やりにでもやりたい事を詰め込んだオープニングができました(10日くらいかかったのかなぁ)。作ってみてわかったことが一つ。「こういった映像系のものを作る時には、ちゃんとタイムラインエディタを使いましょう」です(当たり前だぁ)。今回の方法は、とにかく編集・調整がしにくいのが問題ででした。何度ぶん投げようかと思ったことか……(80秒って意外と長い)。次にやるときは、ちゃんとやります、きっと……さて、気分転換も済んだし、ゲーム本編を作らなきゃだ。がんばろ。
>OPでとてもお世話になったアセット(モデル・エフェクトは除く)
・Fire Music Pack
https://www.assetstore.unity3d.com/jp/#!/content/61607
・DOTween
https://www.assetstore.unity3d.com/jp/#!/content/27676
・Typeface Animater
Unityアクションゲーム制作記 その14 攻撃時の軌跡エフェクトの変更
年末にいろいろあって、久しぶりの更新となった今回は、軌跡エフェクトの変更をしてみました。攻撃の軌跡には、これまでアセットの「X−WeaponTrail」を使っていたのですが、モーションとの相性も悪く「なんとなく微妙だなぁ」と常々思ってました。そこで、ちょっと試しとばかりに、エフェクト用に購入したアセットの中から適当なテクスチャを選び、単純なメッシュにテクスチャを貼り付けて回転させてみたところ、いい感じのエフェクトに! これまで、なんとなく剣先の位置とかモーションにエフェクトをちゃんと合わせないとダメだろうなぁと思い込んでいました。それが、こんな単純な手段でそこそこの見栄えになったことにちょっとびっくりです。
ただ、本当に1枚のメッシュにテクスチャを1枚貼り付けているだけなので、角度が悪いとペラペラの板であることが丸わかりになってしまいます。とはいえ幸いなことに見下ろし視点からそれほど自由に動くこともなく、一気に攻撃がゲームらしくなりました。ついでに、軌跡のテクスチャも下の写真のように4パターン作り、それぞれ試してみたところ、なかなか悪くないエフェクトに。これなら、最小限の手間で武器のレベル表現もできそうな気配です。
ゲーム要素として「成長」を組み込めれば、ゲームが持つ楽しさの大きな一要素となります。まぁ、その分バランスやら大変なことも増えますが、ゲームとして面白くなるのは間違いないのでちょーっとは頑張りたいところ。まだまだやらなければならないことがてんこ盛りの中、やりたいことを増やしてしまうのは不安ですが……なんとかなるっしょ。うん。
Unityアクションゲーム制作記 その13 ちまちまと作業を進める
懸案のダンジョンの生成がなんとかなって、ほっと一息。次に手をつけたのが、かねてよりやらなきゃと思い続けてきた、ボスクラスの敵のロジックを実装すること…ではなく、大量の敵が出現するときにも対応出来るようなオブジェクトプールシステム…でもなく、会話イベントシステムでした。
モーションの新規作成が難しく(単純に作れない)、たいしたものはできないのですが、とりあえず、キャラを表示して会話くらいできるようにしたいなーということで…
・3Dオブジェクトを登場させる
・吹き出しを表示、文字送りをさせる
・アニメーションの切り替え
やれることをこれくらいに絞ってみました。UI(メニュー)を表示するシステムを、少し弄り回すだけでなんとかなりはしました。ついでに欲が出てきて、チュートリアルなどでよくある操作説明をするときに表示する、ダミーカーソル的なものもやってみたいなーと思いつき…無理やり実装。ただし、Canvasに表示させたカーソルの座標を変換して、そのままタップされた座標にしているため、カーソルを動かしている最中に縦・横回転が起きると座標が飛んでしまうというアホ仕様ですが。このため対処療法的にダミーカーソル動作中には縦・横回転をNGにしました。解決策がないわけではないのですが、とりあえず余裕があったら直そう、なくらいで放置することにします。
次にやったのは、操作系の改良です。これまで連打・目押し・チャージと3つの連続攻撃を入れていましたが、どうにも使い分けというか、操作の煩雑さがうっとおしいなあと思い続けてました。そこで、チャージによる連続攻撃をボツにして、連打&目押しで発生したHit数とKill数でポイントを発生させて蓄積、その蓄積されたポイントが一定数あれば、少しの時間タップし続けるだけで必殺技っぽいものを使えるように攻撃の流れを変更しました。
改良により、連打・目押し・チャージ、それぞれの操作によって出せるアクションが明確になり、そこそこ気持ちのいいものに仕上がったかと。とはいえ、タップした場所が細かくブレてしまったり、他の連続攻撃の合間にチャージ要素入れられないかとか余計なことを考えてしまい、意外に「タップし続けている」という状況をどう判定したらいいか、どう組み込めばアクションがより気持ち良くなるか、うまい方法が見つからず手間取っている最中です。
もう一つ操作で追加した要素が、フリック操作によるダッシュ移動です。緊急脱出用とか、連続攻撃中に出すとキャンセルして移動できたり、こちらもそこそこいい感じになっているのですが、ただ高速で移動するだけでは芸がありません。ボスクラスの敵の背後に回り込めたりとか、もーちょっと使い勝手を上げられないか、これまた余計なことを思案中です。
しっかし、そろそろ作り始めてから半年が経過。半年かかっていまだ操作系の調整をしているって…アクションゲームって難しいなぁ。やりたいことは結構入れられたけど、ゴールはまだまだ…とりあえず、がんばろ。うん。
Unityアクションゲーム制作記 その12 ダンジョンを作る
引き続き前回出た課題、シーンに配置したオブジェクトが、直にアプリサイズに影響するということで、ダンジョンを構成するオブジェクトを生成(ダンジョン自体を自動生成するわけではない)するアプローチをしていきました。
作りたいダンジョンはこんな感じ(↓)。
- 部屋は四角のみ(穴開きはなし)
- 部屋の大きさは3×3以下にしない
- 部屋の一辺に一つの通路のみ接続
- 高低差はなし
これくらいの単純なダンジョンであれば、床のある場所の上下左右を調べ、空白であればその方向に壁を置く、やることはこれだけ。ただ、一つ問題が……床と壁のメッシュが分離しているアセットはいいのですが、購入した背景アセットの一つが、床と壁が一体化したメッシュのものでした。
それぞれ別にするのもアレなので、結局は、一体化したパーツに統一してダンジョンを作っていくことに。まぁ、パーツの規格を統一することで、少ない手間でバリエーション(外観だけだけど)を増やせるというものです。
ダンジョンを構成する最小単位のオブジェクトはどんなものを用意すればいいのかなーと、パターンを書き出してみると、どうやら最大16パターンのパーツがあればいい模様。
- 0の位置(上)空白だった場合は+1
- 1の位置(右)空白だった場合は+2
- 2の位置(下)空白だった場合は+4
- 3の位置(左)空白だった場合は+8
と順番に調べて足していけば、必要なパターン番号が求められます。しかも、同じ形状を回転しているだけのものも多いので、それらを省いていくと実際に使われるオブジェクトは、さらに少なく6個で済みます(しかも1個はほぼ未使用)。パターン番号から使うプレハブと回転の変換テーブルを用意しておけば、6個のプレハブを用意するだけで一つのダンジョンの基本形状をまかなえるということですね。
実際は通路に別形状を使いたかったり、一つのダンジョン内で複数の壁や床のバリエーションを使いたかったりするので、もう少しパーツの種類は増えます。それでも、シーンにおいて実体化させるよりは格段にアプリサイズを削減できました。
左が調整前のダンジョンの外観バリエーションが一つ、ステージが二つの状況です。そこから、ダンジョンの外観バリエーションを三つに増やし、ステージも7つ用意しても劇的な変化。ちなみに、このダンジョン作業をしてミニマップを作り終えたくらいでSSDが吹き飛んで作り直しを余儀なくされました……ということで、左側の状況は作り直し前の状況の画像なので、あくまで参考という感じの比較になってしまいましたが……。
とはいえ、当初の目的であるアプリサイズを削減することは達成できたので、ひとまずヨシとしておきます。 なおどれくらいまで一度に表示しても大丈夫なのかなーと広めのマップを作ってみたところ、これくらいが限界っぽい(Zenfone2を使用)。
うーん、全般的におりこうさんな作りにしてないとはいえ、もう少し頑張りたいところだなぁ。まだ知識が全然追いついていないので、最適化までは考えが及ばないのが悲しい現実だけど。ひとまず動く範囲の大きさで抑えつつ、やりたいことを突っ込んで行こう。まだまだ作らなきゃいけないものはわんさかあるからね…がんばろ。
Unityアクションゲーム制作記 その11 アプリサイズで七転八倒
日々、適当仕様のバグ取りに追われながら制作していたとき、ふと唐突にアプリサイズのことが頭をよぎりました。
アプリの省サイズ化は、もう少しやりたいことを突っ込んでからと思っていたのですが、試験勉強のときに部屋の掃除がはかどるように、煮詰まっていたり、やらなければならないことがあるときに限って、本筋とは違うことが気になって仕方ない状態になり……少しはスリムにしておいたほうがいいだろうと、結局手をつけることになりました。
まずは、アプリの中身がどうなっているのかがどうなっているのか調べなきゃ、と見つけたのがここ↓。
ごちゃごちゃとアセットを突っ込みまくっているので、何が出るかなーと思っていたら、使いもしない9MのWAVデータ(テスト用に初期状態として突っ込んでいたファイル。すぐ書き換えられて実際には使用されることはない)やら、初期の頃にメインタイトルの背景として使っていた8Mくらいの画像ファイル(放置していたオブジェクトにアタッチされてた)などが、ログにゴロゴロ出てきました……。これらを整理しながら、テクスチャや音楽データなどのサイズを変更したりして、だいたい60Mあたりに落ち着かせたのですが、ある日、2つのシーンを行き来できるようになったタイミングで、問題が起きました。
正確には問題というか気付いたことが1点、内訳の中になにやら突出してクソでかいサイズのものがある……。巨大なLevelsという項目の中身はなんなのか、しばし検索してみるも、どうにもよくわからず。名称からゲームレベル(=シーン)なのかなとあたりをつけて、試しにステージのオブジェクトを置いている2つのシーンを外してビルド。すると……
すげー減ってる!
ちなみに2つのシーンに置いていたオブジェクトはコレ↑です。いまさらながら中身を確認していくと、パーツ1つで、最大15Kの頂点、9Kの面で構成されていて、FBXのサイズが200K〜300Kくらい。これが50個ほど、1つのシーンに置かれていたのですから、サイズがでかくなるのは当然といえば当然。なのですが、「このアセットかっこいいよねー、モバイルでも動くから大丈夫かなー」と頭の悪い子状態で購入したときには、こんなことになろうとは全く想像していませんでした。
シーンを1個にしてオブジェクト群をON/OFFしたり、メッシュインポートの圧縮設定を変えたり、試しにオブジェクトを増やしてみたり、いろいろ条件を変えて見たところ、シーンに生成されたオブジェクト(+α)が、ビルドしたときにがっつり含まれていると判明。知らないって怖い……。
AssetBundleを利用して、必要に応じてシーン(ステージデータ)を読み込むようにすればいいのでしょうが(1シーンを数Mまで圧縮することもできそう、ふつーのゲームはそうしているんだろうなあ、きっと)、AssetBundleを使うとなると、当然シーンデータをやりくりするためのモノを作らなきゃならないだろうし、そもそも現在のUnityエディタの上でステージを作成する方法自体も手間のかかるもの。パーツの大きさだけが問題なら利用するアセットのサイズが小さいものに変えればいいともいえますが、これもすぐに物理的限界(アプリサイズ100M)を迎えそうで、根本的な解決になりません。設計段階できっちり仕様を決めておく、という当たり前のことをしていなかったツケがきたということでした。
やれるだろうと思っていたことが無理と分かり、折れかけている心をなんとか騙しつつ、なんとか現状でステージを増やせないかアレコレ調べたりしましたが、解決策は見つからず。手間をあまりかけずにいい方法はないか、と思い詰めていたときに降ってきた言葉が「自動生成」でした。
ダンジョン自体の自動生成までやらなくても、↓こんな感じで、
スプレッドシートに書かれたマップ情報からダンジョンの生成をシーンにできないか……しばし悩むこと数日。うん、これならなんとかなるかもしれない。という方法が見つかったので、できるかどうか……いや、できるよにするためにがんばっていこう、きっとなんとかなる!