LoginSignup
1
2

More than 1 year has passed since last update.

[Unity2D]プレイヤーから一番近い敵の角度に向かって攻撃を飛ばす(オートエイムしてPrefabを飛ばす)[C#]

Last updated at Posted at 2022-06-12






最近、趣味でしょぼしょぼゲームを作った。めっちゃ楽しかったけど、嘔吐しそうなほどつまづいたとこを備忘録。







autoaim2.gif

こういう自動で敵の位置に向かって攻撃が飛んでくやつ。






参考文献

たのしい2Dゲームの作り方 Unityではじめるゲーム開発入門






本誌のおまけpdfで三角関数の解説がある。当時おまけpdfまで読み込んでいなくて、後から気がついて喪失感に襲われた。嘘だと言ってよバーニー。。。





環境

Windows 10 Pro 21H1
Unity 2020.3.18f1
Microsoft Visual Studio Community 2019 Version 16.11.15






準備するもの

・プレイヤーキャラ。紹介するコードは全部プレイヤーキャラにアタッチしたスクリプトに記述すること。
・攻撃エフェクト(複数画像のアニメーションにRigidbodyとColliderをつけたりしたPrefabファイルここでは変数nowPrefab)
・敵(全ての敵で共通のTagをつけている前提)
・算数するぞ! っていう気持ち




tagサンプル.png

※敵キャラにつけたTagを利用する。ここでは「Tag Enemy がついているオブジェクト=敵」という考え方で実装する。






概要

流れ

攻撃ボタンが押される

自分から一番近い敵を探す

一番近い敵に攻撃を飛ばす。

連射を防ぐため攻撃中フラグを立てる






まずボタンを押すと攻撃。ここではデフォルトの Fire1 を使う。

Update()でフレーム毎に「Fire1」が押されたか確認。押されたならAttack()メソッドへ。

//オートエイム用角度変数。後で使う。クラス内メソッド外に置く。
float degree = 0.0f;
float rad = 0.0f;
public GameObject nowPrefab;    //発射したいプレハブ。
public float shootSpeed;    //攻撃の速度力。
bool inAttack = false;               //攻撃中フラグ

 void Update()
    {
        if ((Input.GetButton("Fire1")))
        {
	    Attack();
        }
    }






肝心かなめの攻撃処理本体。

public void Attack()
    {
        if (inAttack == false)
        {
            inAttack = true;        //攻撃フラグ立てる。連続で攻撃が発生しないようにするため。
            //↓++++++++++++一番近い敵探し++++++++++++↓
            //  タグEnemyのオブジェクトをすべて取得し、10f以内の最も近いエネミーを取得する。
            GameObject nearestEnemy = null;    //前回の攻撃で一番近かった敵をリセット
            float minDis = 10f;    //オートエイム範囲。お好みで。
            GameObject[] enemys = GameObject.FindGameObjectsWithTag("Enemy");//Enemyタグがついたオブジェクトをすべて配列に格納。
            foreach (GameObject enemy in enemys)    //全Enemyオブジェクト入り配列をひとつづつループ。
            {
                float dis = Vector3.Distance(transform.position, enemy.transform.position);    //プレイヤーキャラとループ中の敵オブジェクトの距離を引き算して差を出す。
                if (dis < minDis)    //オートエイム範囲(10f)以内か確認
                {
                    minDis = dis;    //今んとこ一番近い敵との距離更新。次のループ用。
                    nearestEnemy = enemy;    //今んとこ一番近い敵オブジェクト更新。
                }
            }
	// foreach が終わった時、nearestEnemyにプレイヤーキャラから一番近い敵が入ってる。
            //↑++++++++++++一番近い敵探し++++++++++++↑

            if (nearestEnemy != null)       //オートエイム有効nullチェック。10f以内にタグEnemy存在。
            {
            //↓++++++++++++オートエイム++++++++++++↓
                Vector2 dt = nearestEnemy.transform.position - transform.position;   //nearestEnemyとプレイヤーキャラの距離を引き算。
                rad = Mathf.Atan2(dt.y, dt.x);    //距離をラジアンへ。
                degree = rad * Mathf.Rad2Deg;    //ラジアンを角度へ。
               
                //回転
                Quaternion r = Quaternion.Euler(0, 0, degree);    //プレイヤーキャラからみたnearestEnemyへの角度でQuaternionを用意。
                //発射するPrefabを生成。発射したいnowPrefabをプレイヤーキャラの位置に、rの角度で生成する。
                GameObject SlashObj = Instantiate(nowPrefab, transform.position, r);
            //↑++++++++++++オートエイム++++++++++++↑
                //発射するパワーを用意。
                float x = Mathf.Cos(degree * Mathf.Deg2Rad);    //角度をラジアンに。Horizontal。
                float y = Mathf.Sin(degree * Mathf.Deg2Rad);    //角度をラジアンに。Vertical。
                Vector3 v = new Vector3(x, y) * shootSpeed;    //Vector3生成。 変数shootSpeedを大きくすると力が大きくなる。お好みで。

                Rigidbody2D body = SlashObj.GetComponent<Rigidbody2D>();    //SlashObjの当たり判定取得。
                body.AddForce(v, ForceMode2D.Impulse);    //SlashObjの当たり判定に力を加える。飛んでく。やったぜ。
                Invoke("StopAttack", 0.4f);    //連射を防ぐためのフラグ操作。
                Destroy(SlashObj, 0.3f);    //攻撃オブジェクトを0.3秒後に削除。射程にも影響する。
            }
          }
    }






 //攻撃ディレイ中の再攻撃禁止。Attack内でInvokeで呼ぶことでディレイをしている。
    public void StopAttack()
    {
        inAttack = false;    //攻撃中フラグ下ろす
    }






 まあまあ複雑。改造して使う際、一気にコピペしないで、少しづつ実装してDebug.Log出しながらの方がわかりやすいと思う。



 自作ゲームからかいつまんだコードなので、変数の宣言ぬけとか変なとこあったらごめん。
 ミスがあったらご報告いただければ嬉しいです。











1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2