【Unity】2Dシューティングを作ってみる話 #13

記事をご覧いただき、誠にありがとうございます。
投稿主の無能です。

前回は、パーティクルシステムを使って爆発のエフェクトを作成しました。

今回はその爆発エフェクトをプレイヤーと敵に設定したいと思います。

爆発エフェクトをプレイヤーに設定する

さて、設定すると言ったものの、どのようにすればいいのかまずは考えてみます。

プレイヤーが被弾もしくは敵と衝突したら機体が爆発する、という事で良さそうです。

という事は、プレイヤーが破棄されたのとほぼ同時かその直後に爆発エフェクトが生成されればやられたことを演出できるようになりそうです。

ではそのように実装してみましょう。

爆発エフェクトをスクリプトで生成する

という事で、爆発エフェクトはプレハブ化まで出来ているので、いきなりスクリプトを追記していきます。

このようになります。
PlayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody2D))]
public class PlayerController : MonoBehaviour
{
    [Header("移動関連")]
    [SerializeField] float moveSpeed = 1f;                  // プレイヤーの移動速度
    [SerializeField] float marginX = 1f, marginY = 1f;      // 余白x・y

    [Header("ショット関連")]
    [SerializeField] GameObject playerBullet;               // 弾のプレハブ
    [SerializeField] float bulletSpeed = 10f;               // 弾の速度
    [SerializeField] Transform playerFirePos;               // 発射ポイント
    [SerializeField] float bulletDelay = 1f;                // 発射の閾値

    [Header("バーチャルスティック")][SerializeField] VariableJoystick joyStick;
    [Header("爆発エフェクト")][SerializeField] GameObject playerExplosion;

    Rigidbody2D playerRB;                                   // プレイヤーのRigidbody
    Vector2 moveDirection, min, max;                        // プレイヤーのベクトル,画面サイズの最小ベクトル/最大ベクトル
    Vector2 playerPos;                                      // プレイヤーの移動制限用
    float bulletInterval;                                   // 弾の発射間隔管理用

    void Start()
    {
        // プレイヤーのRigidbodyを取得
        playerRB = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // 入力受付
        InputProcess();

        // バーチャルスティック処理 ---
        // バーチャルスティックに何らかの入力が合った場合
        // (joyStickが0では無い場合)
        if (joyStick.Direction != Vector2.zero)
        {
            // moveDirectionをバーチャルスティックの入力にする
            moveDirection = joyStick.Direction;
        }
        // --- ここまで

        // 弾の発射 ---
        // deltaTimeを加算
        bulletInterval += Time.deltaTime;
        // 発射間隔が閾値未満の場合
        if (bulletInterval < bulletDelay)
        {
            // 処理を中断
            return;
        }
        // スペースキーが押された場合
        if (Input.GetKey(KeyCode.Space))
        {
            // 弾の発射関数を呼ぶ
            PlayerShot(playerFirePos);
        }
        // 発射間隔をリセット
        bulletInterval = 0;
        // --- ここまで

    }

    void FixedUpdate()
    {
        // プレイヤーを動かす
        PlayerMove();
    }

    // 入力受付
    void InputProcess()
    {
        // 入力を正規化して受け取る
        float x = Input.GetAxisRaw("Horizontal");
        float y = Input.GetAxisRaw("Vertical");
        // 入力を正規化する
        moveDirection = new Vector2(x, y).normalized;
    }

    // プレイヤーを動かす
    void PlayerMove()
    {
        // 移動制限
        MoveClamp();
        // プレイヤーを動かす
        playerRB.velocity = moveDirection * moveSpeed;
    }

    // プレイヤーの移動制限
    void MoveClamp()
    {
        // 最後の移動地点を取得
        playerPos = transform.position;
        // ビューポート座標からワールド座標を取得
        min = Camera.main.ViewportToWorldPoint(Vector2.zero);
        max = Camera.main.ViewportToWorldPoint(Vector2.one);
        // 移動を制限する
        playerPos.x = Mathf.Clamp(playerPos.x, min.x + marginX, max.x - marginX);
        playerPos.y = Mathf.Clamp(playerPos.y, min.y + marginY, max.y - marginY);
        // プレイヤーの位置を取得した最後の地点にする
        transform.position = playerPos;
    }

    // 弾の発射
    void PlayerShot(Transform firePos)
    {
        // 弾を生成
        GameObject bulletClone = Instantiate(playerBullet, firePos.position, Quaternion.identity);
        // 弾のRigidbodyに速度ベクトルをつける
        bulletClone.GetComponent<Rigidbody2D>().velocity = new Vector2(bulletSpeed, 0);
    }

    // 接触判定
    private void OnTriggerEnter2D(Collider2D collision)
    {
        // 敵の場合
        if (collision.gameObject.CompareTag("Enemy"))
        {
            // 爆発演出
            PlayerExplosion(collision);
        }
        // 敵の弾の場合
        else if (collision.gameObject.CompareTag("EnemyBullet"))
        {
            // 爆発演出
            PlayerExplosion(collision);
        }
    }

    // 爆発演出
    void PlayerExplosion(Collider2D collision)
    {
        // 接触した方を破棄
        Destroy(collision.gameObject);
        // 自身を破棄
        Destroy(gameObject);
        // プレイヤーの位置に爆発オブジェクトを作成
        Instantiate(playerExplosion, playerPos, Quaternion.identity);
    }
}
ちょっとメンバ変数がごちゃつき始めてきたので、追記するついでに整理しました。

増えたものはplayerExplosionという爆発エフェクトのGameObjectのみです。

PlayerExplosion関数を作成し、OntriggerEnter2Dの処理の中で重複していたDestroyをまとめました。

処理自体は爆発エフェクトを接触したオブジェクトと自身を破棄した直後にinstantiateで生成しただけです。

生成場所はプレイヤーが破棄される直前の位置なので、playerPosで取得していたのでそちらを使い、回転無しで作成します。

爆発エフェクトはアニメーションが終了すると消えるように設定したので、生成するだけで爆発アニメーションが再生され、終了したら自動的に破棄されます。

ではプレハブの爆発エフェクトをPlayerのInspectorビューで設定したら、ゲームを実行して確認します。

PlayerのInspectorビューで爆発エフェクトを設定する

今回の確認事項は、敵の弾と敵自身に接触したら爆発してPlayerが破棄されるかです。

敵の弾に接触したら爆発が起こりPlayerが消えた

敵自身に接触しても爆発が起こりPlayerが消えた

一連の動作は問題無いですね。

次は敵の爆発をやっていきます。

敵に爆発エフェクトを付ける

プレイヤーと全く同じ方法で、敵に爆発エフェクトを付けられます。

しかし同じ色だとつまらないので、色違いの爆発にします。

Explosion_Playerを複製して、名前を「Explosion_Enemy」にします。

Explosion_Playerを複製し名前を「Explosion_Enemy」にする

敵の爆発はプレイヤーほど大きな爆発は不要なので、Start Sizeを1にします。

この辺りの設定はお好みで変更してください。

Start Sizeを1にする

そしたら色を付けます。

Start Colorで好みの色にしたら敵の爆発エフェクトの設定は完了です。

無能は紫にしました。

Start Colorで好みの色にする

ではEnemyCotrollerに爆発の処理を追記しましょう。

EnemyCotroller.cs
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

[RequireComponent(typeof(Rigidbody2D))]
public class EnemyController : MonoBehaviour
{
    [Header("敵の移動スピード")][SerializeField] float moveSpeed = 1f;
    [Header("敵の弾の発射")]
    [SerializeField] GameObject enemyBullet;    // 敵の弾
    [SerializeField] Transform enemyFirePos;    // 発射ポイント
    [SerializeField] float shotSpeed = 5f;      // 弾の速度
    [SerializeField] float shotDelay = 2f;      // 弾の発射の閾値

    [Header("爆発エフェクト")][SerializeField] GameObject enemyExplosion;

    Rigidbody2D enemyRB;                        // 敵のリジッドボディ
    float shotInterval = 0;                     // 弾の発射管理用

    void Start()
    {
        // 敵のリジッドボディを取得
        enemyRB = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // 弾の発射 ---
        // deltaTimeを加算
        shotInterval += Time.deltaTime;
        // 発射間隔が閾値未満の場合
        if (shotInterval < shotDelay)
        {
            // 処理を中断
            return;
        }
        // 弾の発射関数を呼ぶ
        EnemyShot(enemyFirePos);
        // 発射間隔をリセット
        shotInterval = 0;
        // --- ここまで
    }

    void FixedUpdate()
    {
        // 敵を動かす
        EnemyMove();
    }

    // 敵を動かす
    void EnemyMove()
    {
        // 敵に左方向のベクトルを持たせる
        enemyRB.velocity = new Vector2(-moveSpeed, 0);
    }

    // 接触判定
    void OnTriggerEnter2D(Collider2D collision)
    {
        // プレイヤーに接触した場合
        if (collision.gameObject.CompareTag("Player"))
        {
            // 爆発演出
            EnemyExplosion(collision);
        }
        // プレイヤーの弾に接触した場合
        else if (collision.gameObject.CompareTag("PlayerBullet"))
        {
            // 爆発演出
            EnemyExplosion(collision);
        }
        // ObjectDestroyerに接触した場合
        else if (collision.gameObject.CompareTag("ObjectDestroyer"))
        {
            // 自身を破棄
            Destroy(gameObject);
        }
    }

    // 弾の発射
    void EnemyShot(Transform firePos)
    {
        // 弾を生成
        GameObject bulletClone = Instantiate(enemyBullet, firePos.position, Quaternion.identity);
        // 弾のRigidbodyに速度ベクトルをつける
        bulletClone.GetComponent<Rigidbody2D>().velocity = new Vector2(-shotSpeed, 0);
    }

    // 爆発演出
    void EnemyExplosion(Collider2D collision)
    {
        // 接触した方(プレイヤー)を破棄
        Destroy(collision.gameObject);
        // 自身を破棄
        Destroy(gameObject);
        // 爆発エフェクトを生成
        Instantiate(enemyExplosion, transform.position, Quaternion.identity);
    }
}
Playerにした処理と変わりませんね。

ではEnemyプレハブのInspectorビューで爆発エフェクトを設定したら、ゲームを実行して確認します。

EnemyプレハブのInspectorビューで爆発エフェクトを設定する

敵での確認は、PlayerとPlayerの弾に接触したら爆発が起きて消えるかどうかです。

Playerの弾に接触したら爆発エフェクトが再生されて敵が消えた

Playerと接触しても爆発エフェクトが再生されて敵が消えた

これでプレイヤーと敵に爆発の演出がされるようになりました。

まとめ

今回は
  • プレイヤーと敵にやられた時の爆発エフェクトを実装した
という事をやりました。

次回は、Android向けに弾を発射できるボタンを画面上に作りたいと思います。

では、また次回!

コメント