第12回

Wave を5個にする、スコアの実装

プロジェクトの準備

  1. このページは 2Dシューティングゲーム を初心者用に説明したものです。
    ダウンロードした「第11回プロジェクト」から 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] の名前で保存して下さい。

Wave を5個にする

  1. 「第11回プロジェクト」から Wave.unitypackage をダウインロードして下さい。
  2. インターネットエクスプローラーで Wave.unitypackage を Assets にドラッグ&ドラップします。
    Assets/Prefabs に Wave2~Wave5 が追加されます。
  3. ヒエラルキービューの Emitter を選択して Inspector を表示します。
    Prefabs の Wave2~Wave5 を Inspector の Waves にドラッグして下さい。

  4. テストのために Player が爆発しないように修正します。
    テストが終われば、元に戻して下さい。
    /*      if( layerName == "Bullet (Enemy)" || layerName == "Enemy")
            {   // Managerコンポーネントを取得し、GameOverメソッドを呼び出す
                FindObjectOfType<Manager>().GameOver();
                // 爆発する
                spaceship.Explosion();
                // プレイヤーを削除
                Destroy (gameObject);
            }
    */
    
  5. 再生ボタンから X キーでゲームが始まります。
    Wave → Wave 2 → Wave 3 → Wave 4 → Wave 5 → Wave ... と続きます。

スコアの実装

  1. スコアの基本は Score Class を参照して下さい。
  2. 空のゲームオブジェクト(Score GUI)を作成し、Positionは X 0 Y 0 Z 0 にします。
    空のゲームオブジェクト(Score)を作成し、Score GUI の子に設定します。
    空のゲームオブジェクト(HighScore)を作成し、Score GUI の子に設定します。
    ▼Score GUI
        HighScore
        Score
    
  3. Score を選択して、メニューから Component→Rendering→GUI Text を選択します。
    HighScore を選択して、メニューから Component→Rendering→GUI Text を選択します。
  4. Score の Inspector を設定をします。
        Position : X=1 Y=1 Z=0
        Text : 0
        Anchor : upper right
        Font : Assets/Fonts/SAM_5C_27TRG_
        Font Size : 24
    
    HighScore の Inspector を設定をします。
    正しく設定を行うと右上と右下に 0 が表示がされます。
        Position : X=1 Y=0 Z=0
        Text : 0
        Anchor : lower right
        Font : Assets/Fonts/SAM_5C_27TRG_
        Font Size : 24
    
  5. Asset/Scripts/Score.cs を作成して下さい。
    using UnityEngine;
    
    public class Score : MonoBehaviour
    {
        // スコアを表示するGUIText
        public GUIText scoreGUIText;
    
        // ハイスコアを表示するGUIText
        public GUIText highScoreGUIText;
    
        // スコア
        private int score;
    
        // ハイスコア
        private int highScore;
    
        // PlayerPrefsで保存するためのキー
        private string highScoreKey = "highScore";
    
        void Start ()
        {
            Initialize ();
        }
    
        void Update ()
        {
            // スコアがハイスコアより大きければ
            if (highScore < score) {
                highScore = score;
            }
    
            // スコア・ハイスコアを表示する
            scoreGUIText.text = score.ToString ();
            highScoreGUIText.text = "HighScore : " + highScore.ToString ();
        }
    
        // ゲーム開始前の状態に戻す
        private void Initialize ()
        {
            // スコアを0に戻す
            score = 0;
    
            // ハイスコアを取得する。保存されてなければ0を取得する。
            highScore = PlayerPrefs.GetInt (highScoreKey, 0);
        }
    
        // ポイントの追加
        public void AddPoint (int point)
        {
            score = score + point;
        }
    
        // ハイスコアの保存
        public void Save ()
        {
            // ハイスコアを保存する
            PlayerPrefs.SetInt (highScoreKey, highScore);
            PlayerPrefs.Save ();
    
            // ゲーム開始前の状態に戻す
            Initialize ();
        }
    }
    
  6. 作成した Score.cs を Score GUI ゲームオブジェクトにアタッチして下さい。
    Score GUI の Inspector を表示して、Score GUIText に Score GUI/Score を、High Score GUIText に Score GUI/HighScore を設定します
  7. Asset/Scripts/Enemy.cs を修正してスコアを設定します。
    using UnityEngine;
    using System.Collections;
    
    public class Enemy : MonoBehaviour
    {
        // ヒットポイント
        public int hp = 1;
        
        // スコアのポイント
        public int point = 100;
        
        // 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;
            
            // 弾の削除
            Destroy(c.gameObject);
            
            // ヒットポイントが0以下であれば
            if(hp <= 0 )
            {
                // スコアコンポーネントを取得してポイントを追加
                FindObjectOfType<Score>().AddPoint(point);
                
                // 爆発
                spaceship.Explosion ();
                
                // エネミーの削除
                Destroy (gameObject);
                
            }else{
                
                spaceship.GetAnimator().SetTrigger("Damage");
                
            }
        }
    }
    
  8. Asset/Scripts/Manager.cs を修正してハイスコアを保存します。
    using UnityEngine;
    
    public class Manager : MonoBehaviour
    {
        // Playerプレハブ
        public GameObject player;
    
        // タイトル
        private GameObject title;
    
        void Start ()
        {
            // Titleゲームオブジェクトを検索し取得する
            title = GameObject.Find ("Title");
        }
    
        void Update ()
        {
            // ゲーム中ではなく、Xキーが押されたらtrueを返す。
            if (IsPlaying () == false && Input.GetKeyDown (KeyCode.X)) {
                GameStart ();
            }
        }
    
        void GameStart ()
        {
            // ゲームスタート時に、タイトルを非表示にしてプレイヤーを作成する
            title.SetActive (false);
            Instantiate (player, player.transform.position, player.transform.rotation);
        }
    
        public void GameOver ()
        {
            // ハイスコアの保存
            FindObjectOfType<Score>().Save();
    
            // ゲームオーバー時に、タイトルを表示する
            title.SetActive (true);
        }
    
        public bool IsPlaying ()
        {
            // ゲーム中かどうかはタイトルの表示/非表示で判断する
            return title.activeSelf == false;
        }
    }
    
  9. 爆発しないように修正した Player.cs を元に戻して、再生ボタンから X キーでゲームを実行して下さい。
    何度か繰り返すとベストスコアが更新されます。
プロジェクトの詳細は 2Dシューティングゲーム から 「第12回 Waveを5個にする、スコアの実装」を参照して下さい。
第12回 の完成したプロジェクトは、後部の「今回のプロジェクトファイルをダウンロード」からダウンロードすることが出来ます。

ダウンロードした「第12回プロジェクト」は Assets/Scene/Stage.unity のダブルクリックで起動します。
Script にエラーがあるらしく、このままでは動かないのでページ先頭を参考にしてエラーを修正して下さい。

[Previous Chapter ↑] Shooting-11

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