【Unity】弾を加速・減速させる【弾幕シューティング】

f:id:laylowgamelab:20200325231646p:plain

今回は弾を加速させたり,減速させたりする.
考え方をコード付きで解説.
これって加速弾・減速弾って呼ぶのかな?ググってもあんまりヒットしないから一般的ではないのかも.

前回の全方位自機狙い弾を理解している前提.
前回の記事はこちら.

gamelab.hatenablog.com

加速弾・減速弾とは

名前の通り,弾を加速・減速する弾.

「それだけ?」と思うかもしれないが, 弾幕シューティングゲームにおいてそういったちょっとした味付けが非常に重要.

例によって動画をみるのがわかりやすい.

前回の等速弾.

前回の全方位シューティングの挙動と比べると,
弾幕にゲーム性の幅を持たせやすくなっている.

見た目も華やかになるし,遊びの幅を少し広げられる
ガンガンゲームに取り入れていきたい.
と言うわけでスタート.

加速弾の考え方

これまでの弾の速さは等速だった.

そしてその速度を設定していたのは,
弾を射出する敵のスクリプト

var t = Instantiate(eneShot01, transform.position, q);
t.GetComponent<Rigidbody2D>().velocity = vec;

インスタンス化したオブジェクトの velocity に,速度分の大きさを持つベクトル を渡していた.

ではその弾を加速するにはどうすれば良いかというと,
弾のスクリプトに加速処理をプログラムする

ことになる.

加速処理

加速」なので,弾の速さがどんどん速くなっていけば良い.
言い換えると.ちょっとずつ velocity の値を大きくしていけば良い.

つまり,毎フレーム velocity を (例えば) 1.1 倍していけば良さそう.

減速弾の考え方

減速弾も基本的な考え方は加速弾と一緒.

毎フレーム velocity を(例えば) 0.9 倍していけば減速弾になる.

ただし,減速弾は 1点注意点があり,
減速し続けると弾が止まり画面に残り続けてしまう

f:id:laylowgamelab:20200325234101p:plain 弾が画面に残り続けている図.

これを避けるために,減速の際は最低速度を担保し,その速度以下にならないようにする必要がある.

加速・減速を実装する

velocity を一度取り出して,各要素に加速度を掛けて velocity に設定するだけ.
Vector2 にスカラーをかける operator * が用意されているのでそれを使えば良い.

docs.unity3d.com

// まず velocity を取り出す.
var v = GetComponent<Rigidbody2D>().velocity;
// 1.02 を掛けて
v = 1.02f * v;
// velocity に書き戻す
GetComponent<Rigidbody2D>().velocity = v;

減速時の最低速度は,
速度のベクトルの大きさが一定以下ならそれ以上減速しなければ良い.

ベクトル の大きさは, Vector2.magnitude で取得できる.

docs.unity3d.com

       // 5.0 より遅ければ,5.0 で上書き
        if (v.magnitude <  5.0f)
        {
            v = v.normalized * 5.0f;
        }
        GetComponent<Rigidbody2D>().velocity = v;

でOK.

完成コード

加速弾
(初速に1を設定している

public class EneShot02 : MonoBehaviour {

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {

        // 画面外なら消す範囲は省略

        var v = GetComponent<Rigidbody2D>().velocity;
        v = 1.02f * v;

            GetComponent<Rigidbody2D>().velocity = v;


    }
}

減速弾
(初速に 40 を設定している

public class EneShot03 : MonoBehaviour {

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {

        // 画面外なら消す範囲は省略

        var v = GetComponent<Rigidbody2D>().velocity;
        v = 0.98f * v;

        // 5.0 より遅ければ,5.0 で上書き
        if (v.magnitude <  5.0f)
        {
            v = v.normalized * 5.0f;
        }
        GetComponent<Rigidbody2D>().velocity = v;
    }
}

おわりに

今回はコードだけで完結させるためにあえてマジックナンバーを使用している.

実際にゲームを作る際には,
グローバル変数にして,エディタからパラメータを設定できる状態にするべき.
同じスクリプトでいろんな飛び方をする弾を量産できる.