hashibote0から2Dアクションバトルゲームを作ろう!9アレンジ編:ゲームの完成度を高めよう(前半)ツイートシェアはてブGoogle+Pocket0からアクションゲームを作ろう講座その9です。講座も応用編に突入しました。Managerスクリプトの修正この章でやること前章まででゲームを基礎的な要素のみで完成させ、ブラウザで遊べるようにしました。ゲームの楽しさ・面白さという点では大きな不足がありました。今章では発展的な学習をしつつ、ゲームを楽しくする試みを取り入れていきましょう!今回実装する要素一覧この章で実装する内容、及びそこで学ぶ技術は次のようになります。全て終える頃にはよりゲームらしくなっていますよ!ボスの体力をゲージで表示まず手を付けていきたい改善点はボスの体力表示です。UIの機能で表示させる事は同じですが、文字ではなく画像を使った表現に変えたいですね。今回はFillの機能を利用して「体力が減ったら画像が小さくなる」、つまりゲージ形式での表現に変更してみましょう。以下がゲージ本体のサンプル画像です。前章の最後で行ったフォルダ整理を思い出し、Texturesフォルダにインポートしましょう。Imageオブジェクトの追加と設定まず今まで使っていたBossHealthTextオブジェクトは不要になるので削除しておきましょう。新たにゲージ表示を行うImageUIオブジェクトを作成します。オブジェクト名は「BossHealthGage」にしました。テクスチャのセットまで出来たら次は「ゲージが最大まで伸びている状態」でUIの位置・サイズ調整をします。今回は画面最下部に横幅いっぱいに伸ばしてみました。一緒に色も付けておきます。この後はFillの設定を行い、ボスの体力に応じてこのゲージが短くなるようにします。fillとは?テクスチャの一部のみを表示し、その表示量(割合)をスクリプトで制御するにはImageコンポーネントでFillの設定が必要となります。Type]パラメータでFilledを選択し、そこで出現するFill関係パラメータに適切な値を入力します。各パラメータは以下の内容を表しています。Methodテクスチャの非表示・表示をどの方向で行うかを指定します。Origin非表示・表示を開始する時の始点となる位置や方向です。Methodによって選択項目も変化します。Amountテクスチャの表示量(割合)です。これをスクリプトで制御する事でゲージ表示が実現します。0~1の小数で指定します。Clockwise表示・非表示の方向の時計周り・反時計周りを指定します。Methodの設定によっては選択不要です。FillMethodにHorizontalを指定すると、FillAmountの数値を減少させた時テクスチャが右側から非表示になっていきます。今回はこの設定を使用します。他にも選択できるFillMethodの項目を確認しましょう。HorizontalFillAmountの数値によって水平方向に表示・非表示をします。Vertical垂直方向に表示・非表示を行います。90いずれかの角を起点として放射状に行います。180いずれかの縁の一部を起点として放射状に行います。360テクスチャの中心を起点として放射状に行います。これでオブジェクト側の設定は終わりです。スクリプト側の設定ボスの体力表示を行ってきたGameManagerスクリプトの変更を行いましょう。オブジェクトが変わっているので、インスペクターウィンドウからの再セットも忘れずに。ratio;}}int型の変数同士で除算を行っても整数でしか商を得られないので、float型数値で得る為には変数名の頭に(float)という文言を入れる必要があります。これを変数のキャストと言います。これでこの演算を行っている間だけ、変数healthはfloat型のように扱えます。メソッドの引数の変えたので、これを呼び出しているボスのスクリプトにも微修正が必要です。自オブジェクト消去}}}自身の初期体力を体力の最大値とし、この2つの数値から残り体力を割合として算出しています。GameManagerに「BossHealthGage」をセットするのを忘れないでください。変更が完了すれば、ボスの体力が減少した時ゲージも減少するようになっています。ボスの体力を調整ゲームの難易度調整はこれから行っていきますが、ひとまずゲージ機能の確認も兼ねてボスの体力をもっと増やしてみましょう。一度行った事なので大丈夫だと思いますが、ボスの初期体力はpublic型変数で決めている為インスペクターウィンドウから変更できます。エネルギー要素の実装7章でプレイヤーに与えたバリア能力が強力すぎてバランスを崩しています。続いては、これの改善を行いますが、どのようなアプローチで行えば良いのでしょうか?プレイヤーの能力にも何かしら制限を与える事で、ユーザーにもどの能力をいつ使うかという選択肢が発生します。全ての行動にリスクとリターンが存在すればプレイスタイルを1つに限定せずに済みますね。1つの要素のみを難しくしてもバランス調整は成功しません。ゲームの方向性を考えながら、どうすれば全体がより良くなるかを考えると良いでしょう。今回はエネルギーの概念をプレイヤーに持たせ、バリア展開時は大きく、ショット発射時は小さくエネルギーを消費させるようにします。エネルギーが不足すると行動は失敗し、逆に何も行動をしなければエネルギーは回復するようにしてみましょう。エネルギーゲージを用意エネルギー残量を表示するために、復習も兼ねて先ほど行ったゲージ形式を使用しましょう。UIの表示位置としてはプレイヤーの体力アイコンの下が適切でしょうか。サイズも大きくなくて良いでしょう。ここにプレイヤーや弾が隠れると邪魔に感じてしまうので、画像のアルファ値を下げて半透明にする配慮もあるとなお良いです。ゲージの設定をGameManagerスクリプトから行えるよう準備エネルギーゲージは今オブジェクトを準備しただけであり、続いてスクリプトからそれを変更できるようにする準備をする必要があります。それをPlayerControllerスクリプトで行っても問題はないのですが、今回はUI制御をGameManagerスクリプトで行うように決めたので、少々面倒に感じてもしっかり役割分担はさせましょう。以下のようなメソッドを追加すれば良いでしょう。変数image_EnergyGageは先ほどのエネルギーゲージUIを指しています。宣言とインスペクターウィンドウからのセットを忘れずに行ってください。宣言は上の一行を追加すれば大丈夫です。ratio;}エネルギーの消費と回復あとはプレイヤーのスクリプトを変更し、エネルギーのシステムを実装しつつそれをUIに反映させていきます。collider){(省略)}}エネルギーが不足するとバリアは強制解除となりますが、展開と解除だけをすぐ繰り返されても泥沼なので、展開時に一定量のエネルギーを必要とする調整にしています。これでエネルギー機能の実装は完了です。テストプレイを行い、お好みでエネルギーの消費量や回復量を調整してください。プレイヤーの無敵時間の実装もう一つ難易度関連で必要な要素はプレイヤーの無敵時間です。現在プレイヤーの体力は3になっていますが、3発の敵弾を連続して受けると一瞬で負けてしまいます。それでは少し不親切なので、一度敵弾を受けた後は暫くの間当たり判定を無視するようにします。これは俗に無敵時間と呼ばれ、大抵のアクションゲームでは必要とされる要素だと言えます。プレイヤースクリプトを変更していきましょう。float型変数invisibleTimeをまず追加します。ここには残り無敵時間を入れる事にします。この変数に0より大きい値が入っていれば無敵状態として扱い、その間はこの変数を減らし続けるようにすれば良いです。被弾時の無敵関連処理です。1.5秒}後はUpdate()メソッドの最後に残り無敵時間を減らす処理を入れれば良いでしょう。Time.deltaTime;無敵時間の表示を分かりやすくするこれで被弾後の少しの間は無敵となり、敵弾がすり抜けていくようになりました。見た目には変化がなく、いつ無敵が終わるのかが初見では分かりません。無敵中はその事を分かりやすくする為、例えばキャラクターの描画に変化を与えると良いでしょう。今回は単純に「無敵中は半透明」という処理に変更してみます。col;ここまで実装できれば、すぐにバトルが終わってしまうという事も減ったでしょう。この調子で少しずつゲームの品質を上げ続けましょう。ステージセレクト画面の作成タイトル画面でゲーム開始のボタンを押した後、すぐにバトルが始まってしまうようではユーザーは心の準備ができません。タイトルとバトルの間に1クッションが欲しいですね。今回はステージセレクト画面を作成し、そこに差し込みます。これによって、今後複数ボスのバリエーションを増やした時も選んでバトルを開始する事が出来ます。参考レイアウト最低限必要なUIは、この画面がステージセレクトである事を示すロゴとボス選択ボタンです。サンプルゲームではこのような配置になっていました。(現在はまだボスが1体のみですので、ステージ2以降のUIは不要です。)ステージセレクトシーンの作成タイトルシーンを作成した時の事を思い出しながらステージセレクトシーンを開発していきましょう。Scene]で出来ましたね。As]で名前を付けて保存しましょう。シーン名は「StageSelectScene」としておきます。オブジェクトの配置ですが、ひとまず動作確認が出来れば良いので単純なUIをいくつか置くだけでOKです。後で気になり始めたら調整を行うのでも大丈夫でしょう。背景画像もタイトル画面の使いまわしで試してみます。オブジェクトのコピー・ペーストはシーンをまたいでも可能です。Settingsウィンドウを開きます。Build]への登録が必要でしたね。Scenes]ボタンを押下してビルド対象シーンのリストにステージセレクトシーンを加えます。こちらは必須ではありませんが、順番をタイトルシーンとバトルシーンの間にしておくと良いでしょう。ステージセレクト制御スクリプトビルドの設定も終わり、後はスクリプトでシーン制御を行うのみです。今まで作ってきたGameManager、TitleManagerと同じように「StageSelectManager」のオブジェクトとスクリプトを作成しましょう。1」のボタンが押された時にそのメソッドを呼び出す設定をします。タイトル画面の微修正ステージセレクトシーンでやる事はひとまず終了です。続いてタイトルシーンの修正も行います。ボタンを押した時の遷移先シーンがステージセレクトシーンになるようにしましょう。("StageSelectScene");}これでステージセレクト画面をゲームに組み込む作業が終わりました。フェードイン・フェードアウトシーンの数が増えたのは良いのですが、未だシーンの切り替えが瞬時に終わってしまう為、ユーザーにとっては唐突なものに感じられます。切り替え時には何らかの演出があった方が望ましいでしょう。その形の1つが「フェード」です。完全に画面を隠しきったタイミングで次シーンのロードを行います。ロードが終了したら、画面を覆っていたフェードを徐々に透明に戻し、「フェードアウト」が完了します。実装方法についてフェードイン・フェードアウト処理は全てのシーン遷移時に実行します。ゲームオブジェクトはある設定を行わない限りシーン遷移時に全て破棄されます。(その設定は次章で解説いたします。)なので今回は全てのシーンに全く同じ処理をするフェード制御オブジェクトを配置する事にします。フェード具体的な処理内容は以下の段階によって分けられます。読み込み時(Start()メソッド実行時点)フェードオブジェクトを真っ白にし、その後徐々に透明に戻す。(フェードアウト)シーン切り替え開始時フェードオブジェクトを徐々に透明から白にします。(フェードイン)フェードイン完了時(画面が真っ白になった時)LoadScene()メソッドでシーン切り替えをする。画面を覆うフェードオブジェクトを作成し、それを制御スクリプトが透明にしたり白にする動作を組みます。フェードオブジェクトの作成フェード本体はUIのImageで作成しましょう。オブジェクト名は「FadeManager」にします。UIですがここに後でフェード制御のスクリプトも組み込む予定です。画像はセットしなければ白い四角が表示されるので、これをフェード画像として利用します。サイズを変更して画面全体を覆わせてみましょう。Target]パラメータをオフにする変更が必要です。UGUIでは全てのUIはマウスクリック等の検出が可能なのですが、画面を覆っているFadeUIで検出を行ってしまうと後ろにあるUIをクリックできなくなってしまいます。RaycastTargetを外せばこの設定は無効となるので、基本的にボタン等以外のUIではオフにしておくと無難です。最後に注意点として、UIの表示が重なった時はヒエラルキーウィンドウで後ろに存在するUIが上に表示されるという仕様があります。フェードを一番後ろに配置しないと、フェードインしてもボタン等他UIが隠れないという現象が発生します。これでUI部分の準備は完了です。この画像の透明度はスクリプトで制御される為、開発中はアルファ値を0にしておくと他のオブジェクトが隠れなくなり作業がしやすいです。フェード制御スクリプトの作成フェードの動作を行うスクリプトを作成し、先ほどのFadeManagerオブジェクトにアタッチします。このスクリプトでは、単純なフェードの表示・非表示だけでなくシーン読み込みの処理まで行います。読み込みを今までのようにGameManagerやTitleManager等で行った場合、それぞれで毎フレーム「フェードの進行状況」を監視する必要があるからです。同じような処理を複数スクリプトに行わせるよりは、「フェード完了時にシーン読み込み」の処理をFadeManagerに行わせれば簡潔に済みますね。それではスクリプトを作成します。スクリプト名は「Fade」にします。0.0f;}}作成できたらオブジェクトにアタッチし、その後オブジェクトをプレハブ化しましょう。他シーンで使いまわす為です。他シーンへのインスタンスの配置ここまでの作業をステージセレクトシーンで行っていたのなら、タイトルシーンとバトルシーンにこのプレハブのインスタンスを配置します。全てのシーンにFadeManagerオブジェクトが配置されているようにしてください。その際、Canvas内のUIの順番は間違えないようにしましょう。フェードが一番後ろでしたね。後は今まで行っていたシーン切り替えの処理を、LoadScene()からFadeスクリプト内のTransitionScene()メソッドに置き換えるだけです。これを行先シーン名と共に呼び出せば、自動でフェードイン処理とシーン切り替えまでを行ってくれます。TitleManager.cs、StageSelectManager.cs、GameManagerにあるSceneManager.LoadScene()呼び出しをそれぞれ下記に変更してください。("StageSelectScene");これでフェードに関する処理は完了です。使われる演出ですので、一通りの流れは覚えておくと良いでしょう。Find()メソッドについていま書き換えを行ったスクリプトにあったGameObject.Find()というメソッドですが、これは引数内にオブジェクト名を入れると自動的にシーン中からその名前のオブジェクトを探しだし、参照を返してくれるという便利なメソッドです。この処理は少しだけ動作が重たいという弱点もあります。毎フレーム連続で呼び出すなどしてしまうと、ゲームの実行速度が大きく落ちる場合があります。頼りすぎに注意しましょう。(よって現在のスクリプトも本当は悪い例になっています。どこに原因があるかを探してみましょう。)バトル終了時の処理ここはおまけ程度の内容ですが、バトル終了後にプレイヤーが勝ったのかボスが勝ったのかの表示があると分かりやすいですね。UIのTextを使って簡単な文章を表示させてみましょう。今回はTextやImageに対して付加できるEffectsも試してみます。TextとEffectまずはバトルシーンにて戦闘結果表示用のUIオブジェクトを作成します。オブジェクト名は「ResultText」等にしましょう。Canvas内での表示順はFadeManagerより前ならどこでも大丈夫です。その後はTextコンポーネントでフォントサイズ等の調整をします。表示する文字列はスクリプトで制御しますが、最初は適当な文言を入れて見え方を確認し、調整が終わったら文字列を空白にします。それが済んだらTextへのエフェクト付与を試してみましょう。UGUIではTextまたはImageコンポーネントに対して効果を及ぼすエフェクトコンポーネントが存在します。同じオブジェクトに追加で取り付けるだけでOKです。エフェクトコンポーネントは現在以下の2種が存在します。Shadowコンポーネント文字・画像に対して影のように見える部分を追加する。影の色や不透明度は変更可能。Outlineコンポーネント文字・画像に対して輪郭線を付与できる。輪郭線の色や不透明度は変更可能。UV1」というコンポーネントもありますが滅多に使われないので気にしなくて大丈夫です。今回はShadowコンポーネントを追加し、文字に立体感を出してみましょう。Component]ボタンからコンポーネントの追加をします。[UI]→[Effects]→[Shadow]と選択しましょう。Distance]があります。後はゲーム管理スクリプト上で、戦闘結果に応じてこのTextに文字列を設定する処理を追加しましょう。先ほどのコンポーネントを指定するText型のpublic変数text_Resultを用意し、戦闘終了後処理を変更します。戦闘が終了していたら(省略)}これで戦闘結果が画面に表示されるようになりました。次章に続きます応用編の前半はここまでです。後半にも重要知識の説明がありますので、ぜひ開発を続けてみてください。この章の内容を実装しただけでもかなりゲームは遊びやすくなったと思います。「10アレンジ編:ゲームの完成度を高めよう(後半)」チュートリアル2Dunityサンプルチュートリアルこの記事が気に入ったらいいねしよう!最新記事をお届けします。ツイートシェアはてブGoogle+Pocketfeedly0から2Dアクションバトルゲームを作ろう!10アレンジ編:ゲームの完成度を高めよう(後半)0から2Dアクションバトルゲームを作ろう!8ビルドをしてゲームを遊んでみようRECOMMENDこちらの記事も人気です。