3Dシューティングゲームの作り方4 敵との戦闘システムを作る(敵・弾丸・HP処理など) | Unity入門の森 ゲームの作り方

3Dシューティングゲームの作り方4 敵との戦闘システムを作る(敵・弾丸・HP処理など)

Unity 3Dシューティングゲームの作り方


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

前の記事でプレイヤーをルートに沿うように移動させ、一人称視点のシューティングゲームを作ることができました。

前回の記事:

3Dシューティングゲームの作り方3 プレイヤー移動処理・視点変化・カメラ追随処理を開発
前回の記事では背景となるGameObjectをTerrainを使用して配置しました。 前回の記事: 今回ではその背景に指定したルートをプレイヤーが移動するようにしましょう! 定めた場所を通りながら自動的にプレイヤーの向きや進行方向も変更して...

この記事ではシューティングゲームのメイン部分を開発していきます。

敵の生成処理、プレイヤーとの当たり判定&HPゲージの減少処理、そして弾を生成し、敵に向かって飛ばし、敵HPを減らす処理をゲームに組み込んでいきましょう!


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

シューティングゲームの敵を作ろう!

まずは敵ゲームオブジェクトを作成しましょう。

この講座では次の手順で敵を管理します。

  • プレイヤーが指定した範囲に入ってくる→敵を生成する
  • 敵をプレイヤーの方に移動させる。

敵を生成するエリアとなるゲームオブジェクトを作る

まずはプレイヤーが指定した範囲に入ってきたら、敵を生成するようにしましょう!

範囲はルートのポイントと同じように空のGameObjectにColliderをアタッチしたもので表現します。

Colliderには必ず「Is Trigger」にチェックを入れてください。

次の手順を行なってください。

  • メニューからGameObject > 空のGameObjectをクリック。
  • 名前はわかるようなものならなんでもOK(ここではEnemyAreaRoot)。
  • 子ゲームオブジェクトを新しく生成。ここではEnemyAreaと名付けておく。
  • 生成したGameObjectにCollider系のコンポーネントをアタッチする。
  • アタッチしたCollider系のIs Triggerにチェックを入れる。
  • シーン上の好きな位置に配置する。
  • 使いまわせるようにプレハブ化する。

「EnemyArea」プレハブはシーン上のプレイヤーの進行ルートとかぶるように配置してください。

敵ゲームオブジェクトの生成 colliderをアタッチしてisTriggerをON

次に敵を表すプレハブを作成します。

  • 適当な形状のGameObjectを作成(CylinderオブジェクトやCubeオブジェクトなどでOK)
  • プレハブ化する時は名前を「Enemy」にする
  • 当たり判定用のColliderコンポーネントをアタッチし、「Is Trigger」にチェックを入れる

「Enemy」には後々専用のコンポーネントをアタッチします。

見やすくするためにマテリアルをアタッチするのもいいでしょう。

また、「Enemy」も「Player」プレハブと同じようにルートGameObjectの下に実際に表示するモデルを追加していく方が汎用性が高まります。

特定エリアに入ってきたら敵を生成するスクリプトを作る

ここまでで敵を生成する際に使用するGameObjectができました。

「EnemyArea」と「Enemy」の二つのGameObjectで敵を管理します。

次は実際にゲーム進行時に敵を生成できるようにしていきましょう!

そのためにスクリプトを作成する必要があります。

次のサンプルコードの内容で「EnemyArea」スクリプトを新しく作成してください。

作成した「EnemyArea」は必ず「EnemyArea」プレハブにアタッチしてください。

「EnemyArea」コンポーネントには次のパラメータを設定できます。

  • EnemyList: アクティブ化するシーン上の敵のリスト

無事コンパイルに成功したら、次の作業を行なってください。

  • 敵をシーン上に配置する
  • シーンに配置した「EnemyArea」コンポーネントに関連付けたいシーン上の敵を設定する。
EnemyAreaのインスペクター画面の一例

EnemyAreaのインスペクター画面の一例

「EnemyArea」の子GameObjectとして「Enemy」プレハブを配置することで、EnemyAreaごとに敵の位置やバリエーションを含めて設定できます。子オブジェクトの相対位置を変えることでEnemyAreaに付いてくる形で敵の生成場所を指定できます。

ただし、その際は親となる「EnemyArea」を非アクティブ化しないように注意しましょう!

子GameObjectは親GameObjectのアクティブ状況の影響を受け一緒に非アクティブになるからです。

作業が終わったら、再生してみましょう。

問題なければシーンに配置した「EnemyArea」の中にプレイヤーが入るとコンポーネントに設定した敵がアクティブ化して出現するようになります。

敵の生成エリアにプレイヤーが侵入→敵を生成の処理ができましたね。

敵をプレイヤーに向かって移動させる

次は生成した敵をプレイヤーに向かって移動させましょう!

「Enemy」スクリプトを新しく作成し、「Enemy」プレハブにアタッチしてください(複数種類あるときはそれぞれにアタッチ)。

「Enemy」スクリプトの内容は次のものになります。

「Enemy」コンポーネントには次のパラメータが設定できます。

  • Speed: 移動スピード
  • DeadSecond:指定した秒数後に削除するようにするためのもの

コンパイルが成功しましたら、敵がプレイヤーに向かって移動するようになります。

プレイヤーの体力を減らせるようにしよう HPゲージの作り方

敵ができたので、プレイヤーに敵が当たったら体力ケージを減らすようにしましょう!

そのために「Player」クラスを次のように変更しましょう!

コンパイルできたら、「Player」スクリプトに追加したものを「Player」オブジェクトに忘れずに設定しましょう!

  • LifeGage:体力ケージ「LifeGage」をアタッチ
  • Life:100 (好きな体力でもOK)

また当たり判定で必要になるので、「Enemy」プレハブのタグにも忘れずに「Enemy」を設定しましょう!

シューティングゲームの弾を打てるようにしよう

最後にプレイヤーが弾を撃てるようにしましょう!

この講座では敵をクリックしたらプレイヤーが敵を目掛けて弾を打つようにします。

弾用のプレハブを作成する

先に弾を表すプレハブを作成します。

次の手順で「Bullet」プレハブを作成してください。

  • メニューのGameObject > 3D Object > Sphereをクリックし、作成したGameObjectをプレハブにする
  • プレハブのタグに「Bullet」を指定する(のちの処理で当たり判定に利用)
  • isTriggerにチェックを付ける(のちの処理で当たり判定に利用)

作成した「Bullet」プレハブには見分けやすくするためにマテリアルをアタッチするのもいいでしょう。

弾を打つ処理を追加する

新しく「Bullet」スクリプトを作成し、「Bullet」プレハブにアタッチしてください。

「Bullet」スクリプトは単純に最初に設定した方向に移動するものになります。

ここまでできましたら仕上げとして、弾を打つ処理を作成しましょう!

弾を打つ際には「Enemy」スクリプトと「Player」スクリプトに次の内容を追加しましょう!

「Player」スクリプトには次のコードを追加しましょう。

次は「Enemy」スクリプトには次のコードを追加しましょう。

コンパイルできたら再生し、実際に弾を打ってみましょう!

その際に「Player」コンポーネントに追加したフィールドを忘れずにアタッチしましょう!

  • BulletPrefab: 「Bullet」プレハブ

敵をクリックしても弾が出ない場合は「Player」をクリックすると判定されている可能性がありますので、次の対策を行うといいでしょう。

基本的にコンポーネントで定義したOnMouseDownAsButtonメソッドは最も画面手前にあるGameObjectのみに呼ばれるようなので注意しましょう。

  • 「Player」プレハブのルートGameObjectの当たり判定を小さくする。
  • 「Player」プレハブにあるコンポーネントにアタッチされているColliderを外す

敵にも体力を設定してみよう

弾を撃てるようになったので最後に弾が当たったら敵の体力を減るようにしましょう!

体力が0になったら、その敵を削除するようにします。

Enemyスクリプトに次の内容を追加してください。

コンパイルに成功したら、「Enemy」プレハブに次の設定を追加してください。

  • Rigidbodyコンポーネントをアタッチし、Is Kinematicにチェックする
  • Use Gravityのチェックを外す

それでは再生してみて、敵を倒してみましょう

もし弾が当たらない場合は次の原因が考えられるので、それらを修正しましょう!

  • 「Enemy」プレハブのサイズが小さすぎる
  • 「Enemy」コンポーネントのLifeがまだ0以下になっていない
  • 「Bullet」コンポーネントのSpeedの値が大きすぎる
  • 「Bullet」プレハブのサイズが小さすぎる
  • 「Bullet」プレハブのタグが「Bullet」ではない
  • 「Bullet」プレハブにアタッチしているColliderのIs Triggerにチェックが入っていない

まとめ

今回の記事でシューティングゲームに必須の敵との戦闘システムを作りました。

今回特に多く出てきた処理としては当たり判定ですね。

  • ColliderをTriggerにして当たり判定などのイベント的な処理を組み込む

この手法・手順には慣れ親しんでおくとよいでしょう。

また、講座ではゲームに要素を組み込む際に基本的に次の流れに沿っています。

  • ゲームを完成させるための処理を考える
  • 必要なGameObjectを作成し、それ用のコンポーネントを作成しアタッチする
  • 実際の処理はスクリプトで制御する

取り分けてこう作るという決まりはないのですが、先にGameObjectの方を作り画面に見えるようにすると作りやすいかなと思いこうしています。

作り方によっては先にコンポーネントを作ってから、そのコンポーネントの内容に合うGameObjectを作成するなどの方法もありますが、その辺りは好みになります。

また、記事では必要最低限のGameObjectしか追加していませんが、読者の方は自由に作っていってOKです。ガンガン改造していきましょう。

またサンプルコードには数学関係のメソッドを使用しています。理論背景がわからない方には呪文のように思えますが、Unityではそういった方でも簡単に使用できるようにメソッドが提供されています。

もちろん、数学ができるとより自由にGameObjectを操ることができるので勉強するのもいいでしょう。

それでは次の記事に行ってみましょう。

次の記事:

3Dシューティングゲームの作り方5 ゲーム制御処理とTerrain当たり判定の実装
前回までの記事で敵を登場させたり、プレイヤーの体力を減らしたり、弾を撃って敵を倒せるようにしました。 前回の記事: ここまでできるとあとはゲームクリアとゲームオーバー処理を作成するとシューティングゲームの出来上がりです! スコア処理や地面に...

参考用:スクリプトの完成図

ちなみに今回の記事で作成したスクリプトの完成図は次のようになります。

次の記事:

3Dシューティングゲームの作り方5 ゲーム制御処理とTerrain当たり判定の実装
前回までの記事で敵を登場させたり、プレイヤーの体力を減らしたり、弾を撃って敵を倒せるようにしました。 前回の記事: ここまでできるとあとはゲームクリアとゲームオーバー処理を作成するとシューティングゲームの出来上がりです! スコア処理や地面に...

3Dシューティングゲームの作り方講座に戻る>>



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

コメント

  1. やまぴー より:

     はじめまして。いつも参考にさせていただいております。
    質問がありまして、コメントをさせていただいております。

     OnMouseUpAsButton メソッドを利用した弾の生成と発射の処理なのですが、上手く反応しなかったため、プレイヤー側のすべてのコライダーを外して試したのですが、その場合でも、このメソッドは反応しませんでした。

     そこで試しに、プレイヤーのゲームオブジェクトの前面(Z軸が手前になるように)にエネミーを配置した所、こちらは正常に OnMouseUpAsButton メソッドが実行されました。この時、プレイヤーのコライダーの有無は関係ありませんでした。(コライダーの有り無しの両方で試してみました)

     結論としてなのですが、OnMouseUpAsButton メソッドはコライダーの有無に関係なく、あくまでもゲームオブジェクトのZ軸の座標で判定されてしまうのでしょうか。そうなると、想定している弾の生成処理にならないのですが、他に回避する方法がありますでしょうか。それとも、Enemyから ShotBullet メソッドを実行せず、Ray などを使ってプレイヤー側でEnemyの座標を取って弾を生成する、とかでしょうか。

     お手数ではございますが、ご教示いただけますと幸いです。
    よろしくお願いいたします。

  2. やまぴー より:

    先ほどコメントさせていただいたものです。
    申し訳ございません。自己解決いたしました。

    エネミーのゲームオブジェクトを階層構造で作成しており、親オブジェクトはフォルダ代わり、子オブジェクトにゲームオブジェクトの実体を置いて、子オブジェクトにコライダーがアタッチさせていたのが、OnMouseUpAsButton メソッドが動かない原因でした。

     親オブジェクトにコライダーがアタッチしたら、正常に判定を行うようになりました。
    ありがとうございました。

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