ブログ › Unity

敵作成~横スクロールシューティング②【2D】

(2024/1/8 更新)Unity

はじめに

2D横スクロールシューティング作成の2回目になります。
アセットストアで無料公開されている「Warped Space Shooter」をお借りして作成しています。

今回は「敵キャラクターを2パターン」を作成し、倒せるようになるまで進めます。

 ↑このような形になります。

敵作成

敵アニメーション

アニメーションする敵を表示
アニメーションする敵を表示

・解説

アニメーション1枚目のスプライトをシーンに配置し、敵オブジェクトを作成します。
敵オブジェクトにコントローラーを割り当てて敵アニメーションと関連付けることで、アニメーションが再生されます。

・手順

  1. 「Assets>Space Shooter Assets>Artwork>enemy>enemy1.png」をシーンにドラッグ&ドロップ
  2. インスペクターの「Transform>スケール」に(4, 4, 1)を入力
  3. 「Assets>Space Shooter Assets>Artwork>enemy>enemy1.controller」をヒエラルキーの「enemy1」にドラッグ&ドロップ

直進する敵

敵がアニメーションしながら左に進む
敵がアニメーションしながら左に進む

・解説

自分の進行方向に向かって前進するだけのAIを作成します。
「1秒間に進む距離」を公開変数で持たせ、Unityで編集できるようにします。
物理更新処理で進行方向に経過時間を掛け、それを現在位置に足していくことで移動させます。

・手順

  1. プロジェクトの「Assets」を右クリックし、「作成>C# スクリプト」をクリック
  2. Enemyと入力し、ENTERを押す
  3. プロジェクトの「Assets>Enemy」をヒエラルキーの「enemy1」にドラッグ&ドロップ
  4. プロジェクトの「Assets>Enemy」をダブルクリック
  5. Start関数の前に以下のスクリプトを記述
    public float speed = 3;         // 1秒間に進む距離
  1. Update関数の後に以下のスクリプトを記述
    // 物理更新時に処理
    void FixedUpdate()
    {
        // 現在の座標を取得
        Vector3 pos = transform.position;

        // 進行方向に向かって直進
        pos += -transform.right * speed * Time.fixedDeltaTime;

        // 新しい座標に変更
        transform.position = pos;
    }
  1. CTRLを押しながらSキーを押してスクリプト保存
  2. Unityエディタをクリックしてビルド
  1. CTRLを押しながらSキーを押してプロジェクト保存
  1. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー開始
  2. 敵機が左に向かって移動することを確認
  3. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー終了

上下にカーブしながら直進する敵

敵が上下にカーブしながら進む
敵が上下にカーブしながら進む

・解説

動きを表す変数「タイプ」を用意し、その値に応じて「直進のみ」「上下カーブあり」の動きを切り替えます。
タイプは公開変数としてUnity上で編集可能とします。
カーブは「サインカーブ」を使います。
物理更新された回数を記録しておき、その値をサインに渡します。
直進で得た移動量に掛け合わせることで、「上下にカーブしながら直進」する移動量となります。
これを現在位置に足すことで、「上下にカーブしながら直進」が実現できます。

・手順

  1. プロジェクトの「Assets>Enemy」をダブルクリック
  2. 変数「1秒間に進む距離」の前に以下のスクリプトを追加
    // 動きの種類
    public enum ENEMY_TYPE {
        LINE,                       // まっすぐ進む
        CURVE                       // 上下にカーブ
    }

    // 動きの種類
    public ENEMY_TYPE type = ENEMY_TYPE.CURVE;
  1. Start関数の前に以下のスクリプトを追加
    public float cycleCount = 1;    // 1秒間に往復する回数
    public float curveLength = 2;   // カーブの最大距離
    float cycleRadian = 0;          // サインに渡す値
    float centerY;                  // Y座標の中心
  1. Start関数に以下のスクリプトを追加
        // 初期Y座標を「Y座標の中心」として保存
        centerY = transform.position.y;
  1. FixedUpdate関数内にある「新しい座標に変更」処理の前に以下のスクリプトを追加
        // 上下にカーブ
        if (type == ENEMY_TYPE.CURVE)
        {
            if (cycleCount > 0)
            {
                cycleRadian += (cycleCount * 2 * Mathf.PI) / 50;
                pos.y = Mathf.Sin(cycleRadian) * curveLength + centerY;
            }
        }
  1. CTRLを押しながらSキーを押してスクリプト保存
  2. Unityエディタをクリックしてビルド

プロジェクトを保存して、

  1. CTRLを押しながらSキーを押してプロジェクト保存

動作を確認します。

  1. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー開始
  2. 敵機が上下しながら左に向かって移動することを確認
  3. 1秒間に往復する回数「Cycle Count」を変えて動作確認
  4. カーブの最大距離「Curve Length」を変えて動作確認
  5. 確認しずらかったら敵のSpeedを0にして確認
  6. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー終了

衝突処理作成

衝突設定

インスペクター設定
インスペクター設定

・解説

衝突するようにするため、「Circle Collider 2D」と「Rigidbody 2D」を割り当てます。
敵機には両方、自機の弾には「Circle Collider 2D」のみを割り当てます。

2Dで作成しているので、「2D」と付いたコンポーネントを選ぶようにしてください。

・手順

敵機に「Circle Collider 2D」と「Rigidbody 2D」を割り当てます。

  1. ヒエラルキーの「enemy1」をクリック
  2. インスペクターの「コンポーネントを追加」をクリック
  3. 「Physics 2D>Circle Collider 2D」をクリック
  4. インスペクターの「Circle Collider 2D>トリガーにする」にチェックを入れる
  5. インスペクターの「Circle Collider 2D>半径」に(0.15)を入力
  6. インスペクターの「コンポーネントを追加」をクリック
  7. 「Physics 2D>Rigidbody 2D」をクリック
  8. インスペクターの「Rigidbody 2D>重力スケール」に(0)を入力
  9. インスペクターの「Rigidbody 2D>衝突判定」を(連続的)に変更

自機の弾にコンポーネント「Circle Collider 2D」を割り当てます。

  1. プロジェクトの「Assets>shoot1」をダブルクリック
  2. インスペクターの「コンポーネントを追加」をクリック
  3. 「Physics 2D>Circle Collider 2D」をクリック
  4. インスペクターの「Circle Collider 2D>トリガーにする」にチェックを入れる
  5. インスペクターの「Circle Collider 2D>オフセット>X」に(0.05)を入力
  6. インスペクターの「Circle Collider 2D>半径」に(0.05)を入力

弾が小さいままでした。。。スケールを4倍にします。

  1. インスペクターの「Transform>スケール」に(4, 4, 1)を入力
  2. ヒエラルキー左上の「<」をクリック

やられ制御

弾を当てたら敵が消える
弾を当てたら敵が消える

・解説

「体力が失くなったら爆発して消える」というスクリプトを作成し、自機と敵、それぞれに割り当てます。
コライダーを割り当てて衝突範囲を調整することで敵を倒せるようになります。

・手順

  1. プロジェクトの「Assets」を右クリックし、「作成>C# スクリプト」をクリック
  2. Hitと入力し、ENTERを押す
  3. プロジェクトの「Assets>Hit」をヒエラルキーの「enemy1」にドラッグ&ドロップ
  4. プロジェクトの「Assets>Hit」をダブルクリック
  5. Start関数の前に以下のスクリプトを記述
    public int energy = 3;              // 残り体力
  1. Update関数の後に以下のスクリプトを記述
    // 衝突時の処理(トリガー)
    void OnTriggerEnter2D(Collider2D collider)
    {
        // 体力を減らす
        energy--;
        // 体力が無くなった場合
        if (energy <= 0)
        {
            // 自分を削除
            Destroy(gameObject);
        }
    }
  1. CTRLを押しながらSキーを押してスクリプト保存
  2. Unityエディタをクリックしてビルド

プロジェクトを保存して、

  1. CTRLを押しながらSキーを押してプロジェクト保存

動作を確認します。

  1. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー開始
  2. 弾を当てたら敵が消えることを確認
  3. ※体力を1にしても消えない場合は手順を見直してください
  4. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー終了

やられエフェクト

やられアニメーション

命中した時(右下)と爆発した時(左下)のアニメーション、一時的にプレハブを置いての確認
命中した時(右下)と爆発した時(左下)のアニメーション、一時的にプレハブを置いての確認

・解説

スッと消えてよくわからないのでエフェクトでリアクションしてもらいます。

エフェクトの1フレーム目のスプライトをシーンに配置してゲームオブジェクト化し、スケールを4倍にしてアニメーションを割り当て。
プレハブ化してヒエラルキーから削除、これを「Hit」と「explosion」のエフェクトに対して行います。

・手順

  1. 「Assets>Space Shooter Assets>Artwork>hit>hit1.png」をシーンにドラッグ&ドロップ
  2. インスペクターの「Transform>スケール」に(4, 4, 1)を入力
  3. 「Assets>Space Shooter Assets>Artwork>hit>hit1.controller」をヒエラルキーの「hit1」にドラッグ&ドロップ
  4. ヒエラルキーの「hit1」をプロジェクトの「Assets」にドラッグ&ドロップ
  5. ヒエラルキーの「hit1」をクリックし、Deleteキーを押す
  1. 「Assets>Space Shooter Assets>Artwork>explosion>explosion1.png」をシーンにドラッグ&ドロップ
  2. インスペクターの「Transform>スケール」に(4, 4, 1)を入力
  3. 「Assets>Space Shooter Assets>Artwork>explosion>explosion1.controller」をヒエラルキーの「explosion1」にドラッグ&ドロップ
  4. ヒエラルキーの「explosion1」をプロジェクトの「Assets」にドラッグ&ドロップ
  5. ヒエラルキーの「explosion1」をクリックし、Deleteキーを押す

やられアニメーター

指示があった時に初めてアニメーション再生するよう修正
指示があった時に初めてアニメーション再生するよう修正
アニメーションに「画面上で見えなくするため」のフレームを追加
アニメーションに「画面上で見えなくするため」のフレームを追加

・解説

Hitとexplosionのフォルダにあるアニメーションを修正し、終了時に見えなくなるよう最終フレームのスケールを0にします。
また、アニメーション再生のタイミングを指定するためアニメーターコントローラーに空ステートを開始時のステートとして指定、
プロパティ「play」を追加してメインのアニメーションを呼び出すためのトリガーとします。

開始時は何も表示されず、スクリプトでplayトリガーを起動するとアニメーションが再生されるようになります。
この手順はそのための準備になります。

・手順

トリガー「play」がONになった時にはじめてアニメーションが再生されるように設定します。

  1. 「Assets>Space Shooter Assets>Artwork>hit>hit1.controller」をダブルクリック
  2. アニメータービューの右側背景を右クリック
  3. 「ステートの作成>空」をクリック
  4. 「New State」を右クリックし、「レイヤーデフォルトステートとして設定する」をクリック
  5. 「Any State」を右クリックして「遷移を作成」をクリック、そのまま「Hit-Animation」をクリックして矢印を繋げる
  6. インスペクターのチェック「時間をループ」を外し、ループしないように設定
  1. アニメータービューのタブ「パラメーター」をクリック
  2. アニメータービューの左側上部にある「+」をクリックし、「Trigger」をクリック
  3. 「play」と入力してENTERを押す
  4. 「Any State」と「Hit-Animation」の間にある矢印をクリック
  5. インスペクターの「Conditions」右下にある「+」をクリック

スケール0になるフレームを最終フレームに配置し、アニメーション終了時にスプライトが消えるように設定します。

  1. プロジェクトの「Assets>hit1」をダブルクリック
  2. Unityメニューの「ウィンドウ>アニメーション>アニメーション」をクリック
  3. アニメーションビューの「プロパティを追加」をクリック
  4. 「Transform」の左にある「▶」をクリック
  5. 「Transform>スケール」の右にある「+」をクリック
  6. アニメーションビューのタイムライン部、上部にあるフレーム行の「3」をクリック
  7. アニメーションビューのプロパティ部、右上にある「◆+」をクリック
  8. アニメーションビューのタイムライン部、上部にあるフレーム行の「4」をクリックし、4フレーム目に白い縦線を配置して操作対象とする
  9. アニメーションビューのプロパティ部、右上にある「◆+」をクリック
  10. アニメーションビューのプロパティ部、スケールの左にある「▶」をクリック
  11. アニメーションビューのタイムライン部、「スケール.x」の行にある「4フレーム目の◆」をクリック
  12. アニメーションビューのプロパティ部、スケールのx, y, zに(0, 0, 0)を入力

爆発エフェクトのアニメーターコントローラーを設定します。

  1. 「Assets>Space Shooter Assets>Artwork>explosion>explosion1.controller」をダブルクリック
  2. アニメータービューの右側背景を右クリック
  3. 「ステートの作成>空」をクリック
  4. 「New State」を右クリックし、「レイヤーデフォルトステートとして設定する」をクリック
  5. 「Any State」を右クリックして「遷移を作成」をクリック、そのまま「explosion-Animation」をクリックして矢印を繋げる
  6. 「explosion–Animation」をダブルクリック
  7. インスペクターのチェック「時間をループ」を外し、ループしないように設定
  1. アニメータービューのタブ「パラメーター」をクリック
  2. アニメータービューの左側上部にある「+」をクリックし、「Trigger」をクリック
  3. 「play」と入力してENTERを押す
  4. 「Any State」と「explosion-animation」の間にある矢印をクリック
  5. インスペクターの「Conditions」右下にある「+」をクリック

爆発エフェクトのアニメーションを設定します。

  1. プロジェクトの「Assets>explosion1」をダブルクリック
  2. Unityメニューの「ウィンドウ>アニメーション>アニメーション」をクリック
  3. アニメーションビューの「プロパティを追加」をクリック
  4. 「Transform」の左にある「▶」をクリック
  5. 「Transform>スケール」の右にある「+」をクリック
  6. アニメーションビューのタイムライン部、上部にあるフレーム行の「4」をクリック
  7. アニメーションビューのプロパティ部、右上にある「◆+」をクリック
  8. アニメーションビューのタイムライン部、上部にあるフレーム行の「5」をクリックし、5フレーム目に白い縦線を配置して操作対象とする
  9. アニメーションビューのタイムライン部、「スケール.x」の行にある「5フレーム目の◆」をクリック
  10. アニメーションビューのプロパティ部、右上にある「◆+」をクリック
  11. アニメーションビューのプロパティ部、スケールの左にある「▶」をクリック
  12. アニメーションビューのプロパティ部、スケールのx, y, zに(0, 0, 0)を入力
  13. ヒエラルキー左上の「<」をクリックしてプレハブ編集を終了

やられエフェクト制御

命中した時、爆発した時にアニメーション再生
命中した時、爆発した時にアニメーション再生

・解説

命中と爆発を管理するスクリプトを作成し、このスクリプトを呼び出すことでエフェクトが再生されるようにします。

・手順

ゲーム管理スクリプトを作成し、命中エフェクトを管理するための変数を定義します。

  1. プロジェクトの「Assets」を右クリックし、「作成>C# スクリプト」をクリック
  2. GameControllerと入力し、ENTERを押す
  3. ヒエラルキー左上の「+」をクリック
  4. 「空のオブジェクトを作成」をクリック
  5. 「GameController」と入力してENTERを押す
  6. プロジェクトの「Assets>GameController」をヒエラルキーの「GameController」にドラッグ&ドロップ
  7. プロジェクトの「Assets>GameController」をダブルクリック
  8. Start関数の前に以下のスクリプトを記述
    public GameObject hitEffectPrefab;              // 命中エフェクトプレハブ
    public int MAX_HIT_EFFECT = 100;                // 命中エフェクト最大数
    List<GameObject> hitEffects;                    // 命中エフェクト一覧
    int hitIndex = 0;                               // 次に使う命中エフェクトの位置

事前に命中エフェクトを作成して隠しておきます。

  1. Start関数に以下のスクリプトを記述
        // カメラの後ろ位置
        Vector3 hidePos = Camera.main.transform.position - Camera.main.transform.forward;

        // 命中エフェクト事前作成
        hitEffects = new List<GameObject>();
        for (int i = 0; i < MAX_HIT_EFFECT; i++)
        {
            hitEffects.Add(Instantiate(hitEffectPrefab));
            hitEffects[i].transform.position = hidePos;
        }

爆発エフェクトを管理するための変数を定義します。

  1. Start関数の前に以下のスクリプトを記述
    public GameObject explosionEffectPrefab;        // 爆発エフェクトプレハブ
    public int MAX_EXPLOSION_EFFECT = 100;          // 爆発エフェクト最大数
    List<GameObject> explosionEffects;              // 爆発エフェクト一覧
    int explosionIndex = 0;                         // 次に使う爆発エフェクトの位置

事前に爆発エフェクトを作成して隠しておきます。

  1. Start関数内の最後に以下のスクリプトを記述
        // 爆発エフェクト事前作成
        explosionEffects = new List<GameObject>();
        for (int i = 0; i < MAX_EXPLOSION_EFFECT; i++)
        {
            explosionEffects.Add(Instantiate(explosionEffectPrefab));
            explosionEffects[i].transform.position = hidePos;
        }

エフェクトを作成する処理を記述します。

  1. Update関数の次に以下のスクリプトを記述
    // エフェクト再生
    public void playEffect(string id, Vector3 pos)
    {
        GameObject effect = null;
        switch (id)
        {
            // 命中エフェクト
            case "hit":
                effect = hitEffects[hitIndex];
                break;
            // 爆発エフェクト
            case "explosion":
                effect = explosionEffects[explosionIndex];
                break;
        }

        if (effect != null)
        {
            // 位置設定
            effect.transform.position = pos;
            // アニメーション再生
            Animator animator = effect.GetComponent<Animator>();
            animator.SetTrigger("play");
        }
    }
  1. CTRLを押しながらSキーを押してスクリプト保存
  2. Unityエディタをクリックしてビルド

Hitスクリプト側にエフェクトを呼び出す処理を記述します。
まずはGameControllerにアクセスするため、それを保持する変数を作成します。

  1. プロジェクトの「Assets>Hit」をダブルクリック
  2. Start関数の前に以下のスクリプトを記述
    GameController gameController;      // ゲーム管理オブジェクト

タグを使ってGameControllerを取得します。

  1. Start関数に以下のスクリプトを記述
        // ゲーム管理オブジェクトを取得
        GameObject[] gameObjects = GameObject.FindGameObjectsWithTag("GameController");
        gameController = gameObjects[0].GetComponent<GameController>();

体力が無くなったら自分の位置で爆発エフェクトを作成し、エフェクトを再生します。

  1. 「自分を削除」する処理の前に以下のスクリプトを記述
            // 爆発エフェクト再生
            gameController.playEffect("explosion", gameObject.transform.position);

体力が残っていたら自分の位置に命中エフェクトを作成し、エフェクトを再生します。

  1. 条件「体力が無くなった場合」の後に以下のスクリプトを記述
        // 体力が残っている場合
        else
        {
            // 命中エフェクト再生
            gameController.playEffect("hit", gameObject.transform.position);
        }
  1. CTRLを押しながらSキーを押してスクリプト保存
  2. Unityエディタをクリックしてビルド

GameControllerを持ったゲームオブジェクトを検索できるようにタグを割り当てます。

最初から用意されている「GameController」を使います。

  1. ヒエラルキーの「GameController」をクリック
  2. インスペクターの上部、左上にあるタグを「GameController」に変更

命中エフェクト、爆発エフェクトとして扱うプレハブをGameControllerに割り当てます。

  1. プロジェクトの「Assets>Hit1」をインスペクターの「Game Controller(スクリプト)>Hit Effect Prefab」にドラッグ&ドロップ
  2. プロジェクトの「Assets>explosion1」をインスペクターの「Game Controller(スクリプト)>Explosion Effect Prefab」にドラッグ&ドロップ

プロジェクトを保存して、

  1. CTRLを押しながらSキーを押してプロジェクト保存

動作を確認します。

  1. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー開始
  2. 弾を当てたら命中エフェクトが再生されることを確認
  3. 体力が無くなったら爆発エフェクトが再生されることを確認
  4. Unityエディタ上部中央のPlayボタンをクリックしてプレビュー終了

完成

敵が上下移動しながら左に進み、弾を当てると爆発します。

シューティングの「敵作成」完了です。
敵を増やしたり、体力を増やしたり、種類を変えたりして試してみてください。

次回は「自機のやられ、BGM、効果音、スコア」といった辺りを進めようと思います。