Unity C#(2D)で敵にぶつかった時にプレイヤーキャラクター(自分)を吹き飛ばす方法

car-crash IT

敵と自機がぶつかった時に、自機(または敵)を吹き飛ばす方法です。
ぶつかった方向に応じて飛ばす方向を変更する方法がメインです。

スポンサーリンク

敵にぶつかると、自分が弾かれるようにします。
スクリプトは敵に仕込んであって、比較的少ない手間で他の敵や罠などにアタッチできます。

衝突判定

敵が自分を追いかけてくるスクリプトを前に書いたので、それを発展させたいと思います。
コライダー動詞がぶつかった時の処理として、吹き飛ばす側(今回は敵)のスクリプトにvoid OnCollisionEnter2D(Collision2D collision)のように記述して、ぶつかった時に起動するメソッドを作成します。
自分と相手の位置関係を自機.transform.position – this.transform.positionで取得し(この場合FixedUpdateで同じことをしてるので、それを使いまわしてもOK)、normalizedで速度を一定化して、
とりあえずtransformで仮に実行すると、
自分が弾かれることが確認できます。
このtransformの各値に、取得した位置関係のベクトルのxとyを当てはめてやれば、
左から当たれば左に、上から当たれば上に弾かれる状態になります。

壁すり抜け問題の対処

以上、と行きたいところですが、この状態だとまずキャラクター以外のコライダーを持つオブジェクトも吹き飛ばしてしまうので、
これについてはIf文で対象を指定することで解決します。
もうひとつの問題としては、transform.Translateは物理演算ではなく瞬間移動させるので、こんな感じで壁をすり抜けたり、
なんなら壁に埋め込まれる可能性があります。というわけで、別の処理を行う必要があります。
本当はここで衝突判定が連続的かどうかとか、AddForceとかVelocityとかの話になる予定だったんですが、試したらどっちも普通にすり抜けた(速度が速すぎる?)ので、
今回は待機処理でフレームごとの移動速度そのものを遅くし、普通にコライダーに弾かれるようにしてやります。
なんか最近困ったら全部待機処理で解決してるような気もしますが、
とりあえず目標は達成できたようです。
//Unity C#
    public GameObject player;
    //スクリプト内で使いまわす
    public Vector2 targeting;

    void FixedUpdate()
    {
        targeting = (player.transform.position - this.transform.position).normalized;
        if (targeting.x > 0)
        {
            this.GetComponent().flipX = true;
        }
        else
        {
            this.GetComponent().flipX = false;
        }
        this.GetComponent().velocity = new Vector2(targeting.x * 5, 0);
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        //自機に衝突時のみコルーチン実行
        if (collision.gameObject.name == "chara")
        {
            StartCoroutine("Damaged");
        }

    }

    IEnumerator Damaged()
    {
        int i = 0;
        while(i player.transform.Translate(targeting.x, targeting.y*2, 0);
            i++;
        }

    }

完成品はこちら

やりたいことから逆引きするUNITYの使い方まとめ
Unityをやりたいことから学習していけるよう、機能・用途別にまとめたページです。C#の命令別の逆引きは現時点で作っていません。2019の時期に書き始めているので、それより前のバージョンについては言及しません。

コメント

モバイルバージョンを終了