【ゲームの完成】ゲームループ処理の作成とレベルデザイン

Unity タワーディフェンスゲームの作り方


Unity入門の森オリジナル本格ゲーム制作講座はこちら
5種類の本格ゲームの全ソースコード公開・画像&動画による解説付き

前回(9回)は弓関連のUIを追加し、レベルアップや売却が実際に出来るようになりました。

前回の記事↓

武器や攻撃範囲の強化・武器の売買ができるお店システムの作り方
前回(第8回)では、プレイヤーによる弓の配置と、UI画面を作り始めました。 前回の記事↓ 今回はさらにUI画面を作り込み、弓オブジェクトのレベルや制作コスト・売却コスト等をやっていきます。 弓レベルの追加・コスト まず弓のアップ...

今回はついにこのタワーディフェンス講座も最終回。

タイトルやゲームクリア・ゲームオーバーなどの「ゲームループ」部分を主に作って完成させていきます。


【Line登録者限定のプレゼントもあるよ!】

EnemyManagerUIの作成

ゲームループの前に、EnemyManagerの情報表示を作りましょう。

第8回で作ったPlayerStatusUI オブジェクトを複製(CTRL+D)して作られるPlayerStatusUI (1) を EnemyManagerUIと名前を変更し、同じく複製されているPlayerStatusUIスクリプトは削除(右クリックしてRemoveComponent)します。

位置も重なってしまっているので Pos Yを下に下げます。 -500ぐらいが適当です。

そのまま複製され子要素の Text(HP)と Text(GOLD)も名前をText(WAVE)とText(ENEMY)に変更します。

EnemyManagerUI に AddComponent→New Script → EnemyManagerUI と選択し、EnemyManagerUIスクリプトを作成し、下記のように編集します。

メンバ変数は

  • どのEnemyManagerの情報を表示するか(Inspectorで設定)
  • EnemyManagerのWave情報を表示するためのText(Inspectorで設定)
  • EnemyManagerのEnemy数情報を表示するためのText(Inspectorで設定)

の3つです。 Update関数の中では UIのTextにWave情報と敵の数情報をセットしています。

ただ、この

enemyManager.EnemyCnt はまだEnemyManagerスクリプトに無いので EnemyCnt プロパティを追加します。

まだ現在のwaveで出現していない敵の数は waves[wave].patterns.Count になります。

そして、既に出現している敵(Enemy)は FindObjectsOfType<Enemy>().Length で取得し、それを足す事で敵残数を取得できるプロパティにしています(=>を使ったgetプロパティの省略記法です)。

注意点としては waves[wave].patternsListなのでCountで要素数を取得し、FindObjectsOfType<Enemy>()配列なのでLengthで要素数を取得しています。

2スクリプトを修正しましたので、忘れずに2つとも保存をしましょう。
UnityEditorのInspectorでEnemyManagerUIのEnemyManager、Text(WAVE)、Text(GOLD)をセットします。

それではプレイボタンを押して、確認してみましょう。

ENEMYを倒すたびに数字が減っているのが確認できます

GOLDの獲得とダメージ処理

大分ゲームが完成に近づいてきましたが、まだ

  • 敵を倒してもGOLDが増えない
  • 敵がゴール(本拠地)に到着してもHPが減らない

ので、そこもやってしまいましょう。

敵を倒したらGOLDを増やす

矢(Arrow)スクリプトで敵(Enemy)を倒した時に処理を追加します。

FindObjectOfType<Player>() でPlayerオブジェクトを探し、goldを倒した敵の金額(targetEnemy.gold)分増やしています。  

最初からHierarchyに置いてあるオブジェクトであれば、InscpectorからPlayerオブジェクトをセットしておけばいいのですが、動的に生成(Instantiate)されるArrowオブジェクトから、どうやってPlayerオブジェクトのgoldを増やすのか(どうやってPlayerオブジェクトを認識するのか)が結構悩みどころです(講座を作るにあたっても悩みどころです) これには以下のような色々な方法

  • Arrowを発射するBowに設置をしたPlayerオブジェクトを保持させ、バケツリレーのように渡していく
  • Playerオブジェクトは1つしかないので Playerオブジェクトをstatic を使ったシングルトンオブジェクトにする
  • Find系関数を使ってPlayerオブジェクトを探す

等々があるのですが、今回はFind系関数である FindObjectOfType<探したい型>() を使っていますが深い理由はありません(強いて言えば修正するスクリプトが少ない方が混乱が少ないという講座制作上の理由になります)他の方法を使っても問題ありません。

敵がゴール(本拠地)に到着したらHPを減らす

次に敵(Enemy)スクリプトを修正します。

FindObjectOfType<Player>() でPlayerオブジェクトを探し、hpを減らしています。
ArrowスクリプトとEnemyスクリプト、保存をしてUnityEditorで変更を確認してみます。

GOLDが増えHPが減るようになりました。

ゲームループの作成

今更ですがゲームループとは

このように、ゲームの状態(ステート:TITLE や WAVE_CHANGEなど)の遷移をループ状にすることで繰り返しゲームがプレイ出来る状態を言います。

このゲームループを開発序盤で回す(ゲームループなので、良く「回す」と表現されます)のがテストプレイや開発モチベーション維持に結構大事なのですが、今回のタワーディフェンス制作講座では(講座の構成の都合上)最後になってしまいました。申し訳ない・・・。

ステート表示Text

さて。ゲームステート(状態)とゲームループを作っていくんですが、最初にゲームステートを表示するためのTextを追加します。 HierarchyビューのCanvasを右クリックしてUI→Textと選択し、Textを追加します。

  • 名前:Text(State)
  • Anchor Presets:stretch/stretch (SHIFT+ALT)
  • Right:256
  • Font : Assets/Fonts/ShigotoMemogaki-Regular-1-01
  • Text : “らくがきたわーでぃふぇんす”
  • Font Style:BOLD
  • Font Size:90
  • Alignment:中央寄せ

 

このようになります。位置はSceneビューで修正しても構いません。

GameMainスクリプトの作成

Hierarchyビューに、新規オブジェクト(CTRL+SHIFT+N)を作成し、新規ScriptもAddComponent→NewScriptで作成します。

  • 名前:GameMain
  • スクリプト名:GameMain

早速GameMainスクリプトを修正していきましょう。

続きを読む

このコンテンツはパスワードで保護されています。 コンテンツを読みたい方はUnity入門の森ショップ(https://unityforest.stores.jp/)で講座閲覧権を取得してね。

おさらい

これにて、ゲームは完成し10回に渡ってお付き合いしていただいたタワーディフェンス制作講座も(ひとまず)終わりになります。

ここで終わりにさせず、別シーンでタイトル画面を作ったり、ステージセレクトを追加したり、効果音や演出を適切に入れる事でよりゲームとして完成されていくと思います。

このタワーディフェンス作成講座をベースに素敵なゲームが完成した際には是非一報頂けると嬉しいです。 ここまで読んでいただき誠にありがとうございます。

タワーディフェンスゲームの作り方講座に戻る↓

【unityで防衛ゲーム】タワーディフェンスゲームの作り方
今回のunityゲーム開発講座では2DUnityを用いたタワーディフェンスゲームシステムの制作を行っていきます! リアルタイムストラテジー(RTS)ゲームを作ってみたい方におススメです。 講座は全部で10回に分かれており、初めてunityを使ってゲームを作る人でもサクサク進められる講座になっています。 講座の中でunityエディターの使い方やUnity C#の活用法も学べるのでこれからunityでゲーム開発していきたい方はぜひ講座を見ながら実際にプログラムを書いていってください。 自分の好きなゲームステージを作成し、オリジナルのタワーディフェンスゲームを開発していきましょう!


Unity入門の森オリジナル本格ゲーム制作講座はこちら
5種類の本格ゲームの全ソースコード公開・画像&動画による解説付き


【Line登録者限定のプレゼントもあるよ!】

コメント

  1. サウスケイ より:

    一応完成しました!
    内容もわかりやすくまとめていてとても理解しやすかったです!
    これからUnityでゲームを作っていく上で参考にしていきたいと思います!
    ありがとうございました!

    • ばこ より:

      おお!完成おめでとうございます!
      完成報告いただけてとてもうれしいです。
      これからも新しい講座どんどん作っていくのでまたサイト見に来てもらえたらうれしいです。
      こちらこそ最後まで読んでいただきありがとうございました!^^

  2. おこめ より:

    ここ5日くらい、このブログを人生で初めてゲーム作りを完遂させました! 今までも何度か挑戦しようとしては挫折してを繰り返していたので、完成出来てめちゃくちゃ嬉しかったです!
    せっかくなのでこのままUnityゲームジャムに何かしらのゲームを投稿してみようかと思います!

    すばらしいコンテンツをありがとーございました!

    • ばこ より:

      おおー!初のゲーム完成おめでとうございます!^^
      この講座作った甲斐がありました。コメントもいただけてとてもうれしいです。
      ちょうどunityゲームジャムも始まりましたもんね!
      おこめさんの作るゲーム楽しみにしてます。
      次回作の講座ももうすぐ出来上がるのでまた読んでやってください(*’ω’*)

  3. bananan より:

    講座ありがとうございました!

    3週間くらいかけてじっくり読み込みながら作りました
    プログラムの書きかたがとても分かりやすく
    挫折せずに開発まで作りあげるが出来ました

    せっかく作ったので、忘れないうちにオリジナルのタワーディフェンス製作を
    やってみたいと思います!!
    目指せ! Kingdom Rush 超え!!(大きく出たな

    この講座がなければやってみようと思いませんでした
    本当に分かりやすい講座でした
    ありがとうございます!!

    • ばこ より:

      うれしいコメントありがとうございます!^^

      最後まで挫折せずに作れたとのことで講座制作者冥利に尽きます!
      プログラムの書き方なども今後もさらにブラッシュアップさせながら講座制作続けていきます。

      ぜひオリジナルゲーム完成まで進めていただければと思います。
      ゲーム完成したらまたコメント欄などでいつでも教えてくださいね!

      こちらこそ最後まで読んでいただき、実際に手を動かして作っていただきありがとうございました!
      いただいた声を励みにこれからもいろんなゲームプログラミング講座作っていきます!

  4. TETSU より:

    最後まで行くことは出来ましたが、敵が弓矢の射程に入ったら弓矢が飛んでいく矢ごと消えてしまいます。VECTOR3 position関連なのでで三次元座標の値がおかしいのだと思いますが講座通りにプログラムを打ち込んでるのに治らないので、解決方法を教えていただけると幸いです。よろしくお願いします

  5. Unity入門の森 より:

    既に完成させている方も出てきてますし、ちゃんと作ればそうはならないはずですね。

    TETSUさんのコードがどこか間違えてるんでしょうね。
    デバッグもゲームプログラミングにつきものですからね。
    コードやUnityのオブジェクトへのアタッチの過程にミスがないか確認してやってみてください。
    ファイトです!

  6. シモン より:

    C#、Unityの初学者です。
    ばこさんのtwitterを拝見し、こちらの講座を受講して最後まで完成させる事ができました!
    自分のPC上でゲームが遊べる事に感動しました。本当にありがとうございます。

    1点、疑問がありまして、タワーディフェンスの挙動でよく見る「一番ゴールに近い敵を優先で狙う」方法についてです。

    OverlapCircleのLayerMask.GetMask(“Enemy”)取得時に「自分の総合移動値」などをEnemyに持たせておいて条件を付ける事ができれば、やりたい事が可能かな…と想像してしたのですが、実現する方法が分からず、質問させて頂きました。
    よく見る挙動ですし、何かお決まりのプログラムでもあるのでしょうか…?

    長文失礼しました。
    他の講義も受講させて頂きます!

    • すずきかつーき より:

      タワーディフェンス制作講座を担当したすずきかつーきと申します。完成おめでとうございます!

      一番ゴールに近い敵を優先で狙う
      なるほど、確かによくある処理ですね。 そこは丁寧に作ると非常に難解になってしまうので、あえて雑にしてある箇所でした。
      色々な方法がありますが、まず現状の Physics2D.OverlapCircle では、範囲内のEnemyの「どれか」しか返却しないため、実際に複数のEnemyが範囲内に居た場合、どのEnemyを狙うのかはランダムになってしまっています
      (厳密にはUnity内部のルールに従っているとは思いますが)
      それを解消するには、まず Physics2D.OverlapCircle の使用をやめて、代わりに Physics2D.OverlapCircleAll を使う必要があります。
      こちらのメソッドは、範囲内のオブジェクト(正確にはCollider2D)「すべて」を配列にして返却してくれるため、そこからおっしゃる通り「最も移動距離が長いEnemy」を一つ取得するのは良い手だと思います。
      ただ、Enemyスクリプトのデータを扱いたい場合はGetComponent() などして、Collider2DからEnemyを取得する必要が出てきますので注意してください。
      コメント欄に書ききれないのであまり具体的な事が書けなくて申し訳ないですが、頑張ってみてください!!

      • シモン より:

        ご返答ありがとうございます!
        なるほど~ Physics2D.OverlapCircleAllといったメソッドがあるのですね
        こちらをヒントに思った挙動に改造できるか試してみます!

        ありがとうございました。

  7. TDまにあ より:

    なんとか最後まで作れました!
    とても勉強になる講座をありがとうございます。これからじっくり復習していきます!

    よろしければ、今後は『キャラクターにスキルを実装する』や『配置するキャラクターを選択できるようにする』といった機能を学べるとありがたいです。
    中・上級編の講座がでたらまた購入いたしますので、ご検討お願いします。

    • ばこ@Unity入門の森 より:

      最後まで講座取り組んでいただき、またコメントいただきありがとうございます!
      なるほど!
      『キャラクターにスキルを実装する』、
      『配置するキャラクターを選択できるようにする』といった機能
      ↑これら、タワーディフェンスではないですが、次回作のSRPG講座で同種の機能を実装する方法を掲載予定です(まだ執筆中なので必ずしもご希望のものになってるかはわからないですが)。

      今執筆中のものなどがある程度まとまったら初心者向け講座のブースターパックみたいなのを書いてみるのも面白そうだなと思いました。
      ご意見ありがとうございます!

タイトルとURLをコピーしました