コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity 入門】全方位シューティングを作る 第16回 敵を倒したら宝石を落とす

目次

前回のチュートリアル

はじめに

前回は、取得すると経験値が増える宝石を作成しました
今回は、敵を倒したら宝石を落とすようにしていきます

宝石を制御するスクリプトの作成

敵が宝石を落としたら、宝石が少し散らばるように
スクリプトを作成していきます

「Player」スクリプトを作成した時と同様の手順で、
「Gem」スクリプトを作成します

そして、作成した「Gem」スクリプトをコードエディタで開き、
下記のコードを記述します

using UnityEngine;

// 宝石を制御するコンポーネント
public class Gem : MonoBehaviour
{
    public int m_exp; // 取得できる経験値
    public float m_brake = 0.9f; // 散らばる時の減速量、数値が小さいほどすぐ減速する

    private Vector3 m_direction; // 散らばる時の進行方向
    private float m_speed; // 散らばる時の速さ

    // 毎フレーム呼び出される関数
    private void Update()
    {
        // 散らばる速度を計算する
        var velocity = m_direction * m_speed;

        // 散らばる
        transform.localPosition += velocity;

        // だんだん減速する
        m_speed *= m_brake;

        // 宝石が画面外に出ないように位置を制限する
        transform.localPosition = 
            Utils.ClampPosition( transform.localPosition );
    }

    // 宝石が出現する時に初期化する関数
    public void Init( int score, float speedMin, float speedMax )
    {
        // 宝石がどの方向に散らばるかランダムに決定する
        var angle = Random.Range( 0, 360 );

        // 進行方向をラジアン値に変換する
        var f = angle * Mathf.Deg2Rad;

        // 進行方向のベクトルを作成する
        m_direction = new Vector3( Mathf.Cos( f ), Mathf.Sin( f ), 0 );

        // 宝石の散らばる速さをランダムに決定する
        m_speed = Mathf.Lerp( speedMin, speedMax, Random.value );

        // 8 秒後に宝石を削除する
        Destroy( gameObject, 8 );
    }
}

これで、宝石を散らばらせるスクリプトの作成が完了しました

宝石を制御するスクリプトの適用

作成したスクリプトを宝石のプレハブに反映していきます

Unity に戻り、すべての宝石のプレハブを
Ctrl キーを押しながらクリックして選択した状態にして、
「Add Component」ボタンを押して、

入力欄に「Gem」と入力し、表示された「Gem」を選択します

そして、宝石のプレハブを順番に選択して、
「Exp」(取得できる経験値)に、下記のように数値を設定していきます

プレハブ Exp
Gem1 1
Gem2 2
Gem3 3
Gem4 4

これで、宝石のスクリプトの適用が完了し、
宝石を入手した時に取得できる経験値も設定できました

敵を制御するスクリプトの調整

宝石を制御するスクリプトの作成と適用が完了したので、
敵を倒したら宝石を落とすようにしていきます

「Enemy」スクリプトをコードエディタで開き、
ソースコードの先頭に下記のコードを追加します

using System.Linq;

次に、変数の定義に下記のコードを追加します

public Gem[] m_gemPrefabs; // 宝石のプレハブを管理する配列
public float m_gemSpeedMin; // 生成する宝石の移動の速さ(最小値)
public float m_gemSpeedMax; // 生成する宝石の移動の速さ(最大値)

そして、OnTriggerEnter2D 関数の
if ( collision.name.Contains( "Shot" ) ) の最後の
Destroy( gameObject ); の下に下記のコードを追加します

/*
 * 敵が死亡した場合は宝石を散らばらせる
 *
 * 例えば、敵を倒した時に獲得できる経験値が 4 で、
 * 経験値を 1 獲得できる宝石 A と、経験値を 2 獲得できる宝石 B が存在する場合、
 *
 * 1. 宝石 A を 4 個
 * 2. 宝石 A を 2 個、宝石 B を 1 個
 * 3. 宝石 B を 2 個
 *
 * のいずれかのパターンで宝石が散らばる
 */
var exp = m_exp;

while ( 0 < exp )
{
    // 生成可能な宝石を配列で取得する
    var gemPrefabs = m_gemPrefabs.Where( c => c.m_exp <= exp ).ToArray();

    // 生成可能な宝石の配列から、生成する宝石をランダムに決定する
    var gemPrefab = gemPrefabs[ Random.Range( 0, gemPrefabs.Length ) ];

    // 敵の位置に宝石を生成する
    var gem = Instantiate( 
        gemPrefab, transform.localPosition, Quaternion.identity );

    // 宝石を初期化する
    gem.Init( m_exp, m_gemSpeedMin, m_gemSpeedMax );

    // まだ宝石を生成できるかどうか計算する
    exp -= gem.m_exp;
}

これで、敵を倒したら宝石を落とすようになりました

敵のパラメータの調整

最後に、敵が落とす宝石のプレハブの設定と、
宝石の散らばる速さの調整をしていきます

Ctrl キーを押しながらすべての敵のプレハブをクリックして選択した状態にして、
「Gem Prefabs」の左の三角形を押してから入力欄に「4」と入力します

次に、敵のプレハブを1つ1つクリックして選択しながら、
すべての敵のプレハブの「Gem Prefabs」の4つの欄に、
それぞれ宝石のプレハブをドラッグして設定します

そして、敵のプレハブを1つ1つクリックして選択しながら、
すべての敵のプレハブの「Gem Speed Min」と「Gem Speed Max」
(生成する宝石の移動の速さ)を、下記のように設定していきます

プレハブ Gem Speed Min Gem Speed Max
Enemy1 0.0125 0.075
Enemy2 0.0125 0.0875
Enemy3 0.0125 0.1
Enemy4 0.0125 0.125

これで Unity を再生すると、敵を倒した時に、
敵が宝石を落とすようになったことが確認できます

次回は、プレイヤーと宝石の当たり判定を作成していきます

次のチュートリアル

チュートリアル一覧