第11回

エネミーのHP、弾の攻撃力、アニメーションの追加

プロジェクトの準備

  1. このページは 2Dシューティングゲーム を初心者用に説明したものです。
    ダウンロードした「第10回プロジェクト」から Assets/Scene/Stage.unity のダブルクリックで起動します。
    Script にエラーがあるらしく、このままでは動かないのでエラーを修正して下さい。(前回の修正も参考にして下さい)
    .velocity が使われている行を次のように修正して下さい。
    【修正前】
    rigidbody2D.velocity =  ・・・(任意の文字列)
    
    【修正後】
    GetComponent<Rigidbody2D>().velocity = ・・・(任意の文字列)
    
  2. Background.cs の次の行を修正して下さい。
    【修正前】
        renderer.sharedMaterial.SetTextureOffset ("_MainTex", offset);
    
    【修正後】
        GetComponent<Renderer>().sharedMaterial.SetTextureOffset ("_MainTex", offset);
    
  3. Player.cs の次の行を修正して下さい。
    【修正前】
        // ショット音を鳴らす
        audio.Play();
    
    【修正後】
        // ショット音を鳴らす
        GetComponent<AudioSource>().Play();
    
  4. 修正が終わるとエラーが消えて実行可能になります。
    再生ボタンをクリックするとゲームタイトルが表示されて X キーでゲームが始まります。
    メニューの File→Save Scene as から [Main] の名前で保存して下さい。

HP と Power の実装

  1. HP(ヒットポイント)と攻撃力(power)を実装します。
    Asset/Scripts/Enemy.cs を修正します。
    public int hp = 1; がヒットポイントで、Inspector から設定することが出来ます。
    hp = hp - bullet.power; でヒットしたときに hp を減らします。
    Debug.Log() で hp の値を印字してみました。
    if (hp <= 0) { ・・・ } で hp が0以下になればゲームオーバーです。
    using UnityEngine;
    using System.Collections;
    
    public class Enemy : MonoBehaviour
    {   public int hp = 1;      // ヒットポイント
        Spaceship spaceship;    // Spaceshipコンポーネント
    
        IEnumerator Start ()
        {   // Spaceshipコンポーネントを取得
            spaceship = GetComponent<Spaceship> ();
            // ローカル座標のY軸のマイナス方向に移動する
            Move (transform.up * -1);
            // canShotがfalseの場合、ここでコルーチンを終了させる
            if (spaceship.canShot == false)
            {   yield break;    }
            while (true)
            {   // 子要素を全て取得する
                for (int i = 0; i < transform.childCount; i++)
                {   Transform shotPosition = transform.GetChild (i);
                    // ShotPositionの位置/角度で弾を撃つ
                    spaceship.Shot (shotPosition);
                }
                // shotDelay秒待つ
                yield return new WaitForSeconds (spaceship.shotDelay);
            }
        }
    
        // 機体の移動
        public void Move (Vector2 direction)
        {   GetComponent<Rigidbody2D>().velocity = direction * spaceship.speed;
        }
    
        void OnTriggerEnter2D (Collider2D c)
        {   // レイヤー名を取得
            string layerName = LayerMask.LayerToName (c.gameObject.layer);
            // レイヤー名がBullet (Player)以外の時は何も行わない
            if (layerName != "Bullet (Player)") return;
            // PlayerBulletのTransformを取得
            Transform playerBulletTransform = c.transform.parent;
            // Bulletコンポーネントを取得
            Bullet bullet =  playerBulletTransform.GetComponent<Bullet>();
            // ヒットポイントを減らす
            hp = hp - bullet.power;
    Debug.Log("hp -> " + hp);
            // 弾の削除
            Destroy(c.gameObject);
            // ヒットポイントが0以下であれば
            if(hp <= 0 )
            {   spaceship.Explosion (); // 爆発
                Destroy (gameObject);   // エネミーの削除
            }
        }
    }
    
  2. Asset/Scripts/Bullet.cs を修正します。
    public int power = 1; が攻撃力で、Inspector から設定することが出来ます。
    using UnityEngine;
    
    public class Bullet : MonoBehaviour
    {   public int speed = 10;      // 弾の移動スピード
        public float lifeTime = 1;  // ゲームオブジェクト生成から削除するまでの時間
        public int power = 1;       // 攻撃力
    
        void Start ()
        {   // ローカル座標のY軸方向に移動する
            GetComponent<Rigidbody2D>().velocity = transform.up.normalized * speed;
            // lifeTime秒後に削除
            Destroy (gameObject, lifeTime);
        }
    }
    
  3. 下手な私には Player がすぐ爆発して HP のテストが出来ません。
    そこで Player.cs の次の行をコメントにしてテストします。
        // レイヤー名がBullet (Enemy)またはEnemyの場合は爆発
        /*if( layerName == "Bullet (Enemy)" || layerName == "Enemy")
        {
            // Managerコンポーネントをシーン内から探して取得し、GameOverメソッドを呼び出す
            FindObjectOfType<Manager>().GameOver();
    
            // 爆発する
            spaceship.Explosion();
    
            // プレイヤーを削除
            Destroy (gameObject);
        }
        */
    
  4. Assets/Prefabs/Wave をヒエラルキービューにドラッグします。
    Wave プレハブの3つの Enemy を選択し、HP の値を 10 にして Apply ボタンで更新してから削除します。
  5. このままでは NullReferenceException が発生する場合があるようです。
    Shooting-10 のスクリプトの実行順を参照して設定して下さい。
    これでエラーが消えて正常に実行されるようです。
    Console タブをクリックして実行して Debug.Log("hp -> " + hp); がゼロになると爆発することを確かめて下さい。

ダメージを受けた時の表現

ここからは操作の方法が解り難いので 2Dシューティングゲーム「第11回 エネミーのHP、弾の攻撃力、アニメーションの追加」を合わせて参照して下さい。
第11回 の完成したプロジェクトは、後部の「今回のプロジェクトファイルをダウンロード」からダウンロードすることが出来ます。
また Animation の基本的な使い方は アニメーション に掲載しています。

  1. アニメーター・レイヤーの作成
  2. アニメーションを作成します。
  3. トリガーを作成します。
  4. スクリプトを修正します。
  5. Damage ステートから Dummy ステートへの Transition も同じ設定を行います。
    ただし、Has Exit Time をチェックした状態で、Exit Time を1に設定してください。
    Enemy に弾が当たると赤くなり、数発被弾すると爆発します。

プレイヤーの無敵時間

  1. ゲーム開始時にプレイヤーを点滅させ、無敵の状態を実装します。
    実装方法はエネミーのダメージアニメーションの実装と同じです。
  2. Assets/Animations/Player/Player をダブルクリックして Animator ウィンドウを開きます。
    Animator/Layers タブから「+」をクリックして、名前を Invincible Layer にします。
    Invincible Layer 右のマークをクリックして Weight を1にします。
  3. Scene ビューに切り替えて Assets/Prefabs/Player をシーンビュー上にドラッグします。
  4. Assets/Animations/Player 上で右クリックして Create→Animation を選択して Invincible を作成します。
    Invincible の Inspector から Loop Time にチェックします。
  5. 作成した Invincible を Animator ウィンドウの Invincible Layer にドラッグします。
    Invincible を右クリックして Set as Layer Default State を選択すると規定値が Invincible に切り替わります。
    (最初から規定値に設定されているかも)
  6. Animator ウィンドウ(Invincible Layer)上で右クリックして Create State→Empty で Dummy ステートを作成します。
    Invincible を右クリックして Make Transition で Invincible から Dummy への Transition を作成します。
    作成した Transition の Inspector から Exit Time は 3 にして、3回 Invincible アニメーションをループさせます。
  7. ヒエラルキービューの Player を選択した状態で、メニューから Windows→Animation で Animation ウインドウを開きます。
    開いたら Normal アニメーションが選択されているので、Invincible アニメーションに変更します。
  8. Animation ウインドウの Add Property ボタンで Sprite Renderer→Enabled と Box Collider 2D→Enabled の2つを追加します。
  9. 0フレーム目はオフに、60フレーム目はオンにします。
    ただし、Box Collider 2Dのキーは削除してください。
    Invincibleアニメーション再生中にコライダーを無効化し、当たり判定を発生させないことで無敵を実現させます。
    これを交互に60フレームまで「オフ、オン、オフ、オン...」というようにキーを打ち込んでください。
    この作業を楽にする方法として、キーのコピー&ペーストがあります。
    キーを選択し (Ctrl)+C でコピーしたら 0:10 の文字があるところをマウスでクリックし (Ctrl)+V でペーストして下さい。
    (次の画像のようにキーを設定するとオン・オフが切り替わるようです)

  10. ヒエラルキービューの Player を Inspector の Apply ボタンで更新してから削除して下さい。
    再生ボタンでゲームを開始すると点滅の無敵状態が3秒間続きます。

[Next Chapter ↓] Shooting-12
[Previous Chapter ↑] Shooting-10

前田稔の超初心者のプログラム入門
超初心者のプログラム入門(Unity)