超初心者のゲーム開発記~Unity~

超初心者がUnityでゲーム(目標はAndroidアプリ )を開発していくブログです!

【Unity公式チュートリアル】 サバイバルシューター part.9 敵を攻撃する!

こんにちは!ヤギです!

Unity公式チュートリアルのサバイバルシューターをやってみるpart.9になります。

記事概要

今回の記事では、敵を攻撃する方法についてご説明していきます。
プレイヤーの銃から弾が発射されるようにしていきます!
f:id:yagigame:20181118150717p:plain
※part.9に対応する公式チュートリアルは、
Harming Enemies - Unityとなります。
※前回の記事はこちら
www.yagigame.com

銃を撃つエフェクトの作成

まず初めに、銃を撃つエフェクトを作っていきます。
1. Project > Assets > Prefabs > GunParticles > Inspector > Particle System > ギアマークをクリックし、Copy Componentを選択します。
f:id:yagigame:20181118111451p:plain
2. Hierarchy > Player > GunBulletEnd > Inspector > Transform > ギアマークをクリックし、Paste Component As Newを選択します。
f:id:yagigame:20181118111748p:plain
3. Hierarchy > Player > GunBulletEnd > Inspector > Add Componentを選択し、Line Rendererコンポーネントを追加します。
※Line Rendererコンポーネントを利用して、レーザーのような射線を描写していきます!
4. Line Rendererコンポーネントを以下の内容に修正します。
・Materials > Element0 > LineRenderMaterial
・Width > 0.05
・Line Renderer > すぐ左のチェックをオフにします。※デフォルトでは描写せず、銃を撃った時のみ描写するようにします。
f:id:yagigame:20181118113419p:plain
5. Hierarchy > Player > GunBulletEnd > Inspector > Add Componentを選択し、Lightコンポーネントを追加します。
※銃を光らせるエフェクトを追加します。
6. Lightコンポーネントを以下の内容に修正します。
・Color > 黄色
・Ligh > すぐ左のチェックをオフにします。※デフォルトでは光らせず、銃を撃った時のみ光るようにします。
f:id:yagigame:20181118113819p:plain
7. Hierarchy > Player > GunBulletEnd > Inspector > Add Componentを選択し、Audio Sourceコンポーネントを追加します。
※銃の効果音を追加します。
8. Audio Sourceコンポーネントを以下の内容に修正します。
・Audio Clip > Player GunShot
・Play On Awake > チェックをオフにします。※ゲーム開始と共に音を鳴らさず、銃を撃った時のみ鳴るようにします。
f:id:yagigame:20181118113950p:plain
※これで銃を発射するエフェクトが完成しました。

弾を撃つスクリプトを作成

1. Project > Assets > Scripts > Player > PlayerShootingをHierarchy > GunBarrelEndにドラッグし適用します。
2. PlayerShooting.csを弾を撃つためのスクリプトとして作成していきます。Rayという機能を使用しています。
※スクリプト内に解説を記載しています。

using UnityEngine;

public class PlayerShooting : MonoBehaviour
{
    public int damagePerShot = 20; //弾のダメージ
    public float timeBetweenBullets = 0.15f; //弾を撃つ間隔
    public float range = 100f; //弾の飛距離

    float timer; //経過時間
    Ray shootRay = new Ray(); //rayを、弾の攻撃範囲とする
    RaycastHit shootHit; //弾が当たった物体
    int shootableMask; //撃てるもののみ識別する
    //弾を打った時のエフェクト
    ParticleSystem gunParticles;
    LineRenderer gunLine;
    AudioSource gunAudio;
    Light gunLight;
    float effectsDisplayTime = 0.2f;

    void Awake ()
    {
        //Shootable Layerを取得
        shootableMask = LayerMask.GetMask ("Shootable");
        //コンポーネントを取得
        gunParticles = GetComponent<ParticleSystem> ();
        gunLine = GetComponent <LineRenderer> ();
        gunAudio = GetComponent<AudioSource> ();
        gunLight = GetComponent<Light> ();
    }

    void Update ()
    {
        //経過時間を計測
        timer += Time.deltaTime;

        //弾を打つボタンを押した時、かつ経過時間が弾を打つ間隔よりも大きい場合
		if(Input.GetButton ("Fire1") && timer >= timeBetweenBullets && Time.timeScale != 0)
        {
            //弾を打つ
            Shoot ();
        }

        //経過時間がエフェクトの表示時間よりも大きくなった場合
        if(timer >= timeBetweenBullets * effectsDisplayTime)
        {
            //エフェクトを非表示にする
            DisableEffects ();
        }
    }

    //銃を撃つエフェクトをオフにする処理
    public void DisableEffects ()
    {
        gunLine.enabled = false;
        gunLight.enabled = false;
    }

    //弾を撃つ処理
    void Shoot ()
    {
        //経過時間を初期化
        timer = 0f;

        //弾を撃つエフェクトをオンにする
        gunAudio.Play ();
        gunLight.enabled = true;

        //弾を連写することを想定して、オフにしてからオンにする
        gunParticles.Stop ();
        gunParticles.Play ();

        //射線のスタート位置を設定する
        gunLine.enabled = true;
        gunLine.SetPosition (0, transform.position);

        //弾の攻撃範囲のスタート位置を設定する
        shootRay.origin = transform.position;
        //弾の飛んでいく方向を設定する
        shootRay.direction = transform.forward;

        //弾を飛ばし、(Rayを飛ばし、障害物に当たった場合
        if(Physics.Raycast (shootRay, out shootHit, range, shootableMask))
        {
            //弾が当たった障害物のEnemyHealthスクリプトコンポーネントを取得する
            EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> ();

            //EnemyHealthスクリプトコンポーネントがnullではない場合(敵に弾が当たった場合)
            if(enemyHealth != null)
            {
                //敵にダメージを与える
                enemyHealth.TakeDamage (damagePerShot, shootHit.point);
            }
            //射線を障害物で当たった場所で止める
            gunLine.SetPosition (1, shootHit.point);
        }
        //障害物に当たらなかった場合
        else
        {
            //射線を弾の飛距離分表示する
            gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range);
        }
    }
}

3. Hierarchy > Player > Inspector > Applyをクリックし、変更内容をPlayer Prefabに反映します。
f:id:yagigame:20181118142308p:plain
※これで弾を撃つスクリプトが完成しました。

EnemyMovement.csを修正

1. EnemyMovement.csを修正します。
※敵とプレイヤーが生きている場合のみ、敵を移動させるようにします。

using UnityEngine;
using System.Collections;

public class EnemyMovement : MonoBehaviour
{
    Transform player;
    PlayerHealth playerHealth; //プレイヤーのHP
    EnemyHealth enemyHealth; //敵のHP
    UnityEngine.AI.NavMeshAgent nav; //NavMesh Agent(敵)

    void Awake ()
    {
        //プレイヤータグのゲームオブジェクトを探し、場所を取得する
        player = GameObject.FindGameObjectWithTag ("Player").transform;
        playerHealth = player.GetComponent <PlayerHealth> (); //プレイヤーのHPを取得する
        enemyHealth = GetComponent <EnemyHealth> (); //敵のHPを取得
        //NavMeshAgentコンポーネントを取得する
        nav = GetComponent <UnityEngine.AI.NavMeshAgent> ();
    }

    void Update ()
    {
        //敵とプレイヤーが生きている場合
        if(enemyHealth.currentHealth > 0 && playerHealth.currentHealth > 0)
        {
            //NavMesh Agent(敵)をプレイヤーに向かって動かす
            nav.SetDestination (player.position);
        }
        //敵もしくは、プレイヤーが倒されている場合
        else
        {
            nav.enabled = false;
        }
    }
}

※これで、敵とプレイヤーが生きている場合のみ、敵が移動するようになりました。

PlayerHealth.csの修正

1. PlayerHealth.csを修正します。
※プレイヤーが倒された場合、弾を撃てなくします。

using UnityEngine;
using UnityEngine.UI; //UIを使うために必要
using System.Collections;
using UnityEngine.SceneManagement;

public class PlayerHealth : MonoBehaviour
{
    public int startingHealth = 100; //スタート時点のHP
    public int currentHealth; //最新のHP
    public Slider healthSlider; //HPバー
    public Image damageImage; //攻撃された時の画像
    public AudioClip deathClip; //倒された時の効果音
    public float flashSpeed = 5f; //攻撃された時の画像の表示速度
    public Color flashColour = new Color(1f, 0f, 0f, 0.1f); //攻撃された時の画像の色

    Animator anim; //アニメーション
    AudioSource playerAudio; //音楽
    PlayerMovement playerMovement; //PlayerMovementスクリプト
    PlayerShooting playerShooting; //PlayerShootingスクリプト
    bool isDead; //プレイヤーが倒されているかのフラグ
    bool damaged; //プレイヤーがダメージを受けているかのフラグ

    void Awake ()
    {
        //コンポーネントを設定
        anim = GetComponent <Animator> ();
        playerAudio = GetComponent <AudioSource> ();
        playerMovement = GetComponent <PlayerMovement> ();
        playerShooting = GetComponentInChildren <PlayerShooting> ();

        //体力を初期化
        currentHealth = startingHealth;
    }

    void Update ()
    {
        //プレイヤーがダメージを受けた場合
        if(damaged)
        {
            //攻撃された時の画像の色を設定する
            damageImage.color = flashColour;
        }
        //ダメージを受けていない場合
        else
        {
            //攻撃された時の画像の色をクリアする
            damageImage.color = Color.Lerp (damageImage.color, Color.clear, flashSpeed * Time.deltaTime);
        }
        //ダメージを受けているかのフラグをオフにする
        damaged = false;
    }

    //プレイヤーが攻撃された時の処理
    public void TakeDamage (int amount)
    {
        //ダメージを受けているかのフラグをオンにする
        damaged = true;

        //プレイヤーのHPを減らす
        currentHealth -= amount;

        //HPバーを減らす
        healthSlider.value = currentHealth;

        //攻撃を受けた時の効果音を鳴らす
        playerAudio.Play ();

        //HPが0以下になった場合、かつ既にたい押されていない場合、倒される
        if(currentHealth <= 0 && !isDead)
        {
            Death ();
        }
    }

    //プレイヤーが倒された場合の処理
    void Death ()
    {
        //プレイヤーが倒されているかのフラグをオンにする
        isDead = true;

        //弾を撃つエフェクトをオフにする
        playerShooting.DisableEffects ();

        //倒された時のアニメーションのフラグをオンにする
        anim.SetTrigger ("Die");

        //倒された時の効果音を設定する
        playerAudio.clip = deathClip;
        //倒された時の効果音を鳴らす
        playerAudio.Play ();

        //プレイヤーを動けなくする
        playerMovement.enabled = false;
        //弾を撃てなくする
        playerShooting.enabled = false;
    }

    public void RestartLevel ()
    {
        SceneManager.LoadScene (0);
    }
}

※これでプレイヤーが倒された場合、弾が撃てなくなります。

実行してみましょう!

マウスを左クリックすると弾が発射され、敵を倒すことができれば大成功です!
https://yagigameblog.tumblr.com/post/180229468357/unity公式チュートリアル-サバイバルシューター-part9-敵を攻撃する

次回予告

次回は、敵を倒した時に加算されるスコア機能を作成していきます!
次回に対応する公式チュートリアルは、「Scoring points」です!

読んでいただきありがとうございました!