YKpages

ロボット分野で勉強したことのまとめ

Unity ゲーム開発日記:敵を作る

はじめに

今回は敵を作っていきます

まずイメージを作成

プレイヤーは四角形にしたので、 敵は丸にします

f:id:kato_robotics:20181103222143p:plain

ゲームウインドウではこんな感じです

f:id:kato_robotics:20181103222246p:plain

敵(Enemy)を作成

Create > 2D Objects > Sprite を選択して、名前は「Enemy」とします

Sprite のイメージには先ほど作成した Enemy 用のイメージを選択

Playerと同じようにRigidbodyをアタッチします

EnemyManagerを作成

まず、空のオブジェクトを作成して名前を「EnemyManager」とします

新規のC#スクリプトを作成して、「EnemyManager」とします

     void Start () 
    {
        for(int i = 0; i < 10; i++)
        {
            Instantiate(enemy, new Vector3(10f, 10f, 0f), Quaternion.identity);
        }
    }

とりあえずStart関数では、Enemyを10体作成するようにしました

原点に置くとPlayerとかぶってしまうので遠くに置いています

f:id:kato_robotics:20181104015229p:plain

Enemyを動かす

EnemyDriver.csというスクリプトを作成します

public class EnemyDriver : MonoBehaviour {

    public float enemySpeed = 1.0f;
    Rigidbody enemyRigidbody;

    // スクリーンの大きさ
    Vector3 min;
    Vector3 max;

    // 進行方向
    Vector3 enemyDirection;

    void Start () {
        enemyRigidbody = GetComponent<Rigidbody>();
        // スクリーンの大きさを取得
        min = Camera.main.ScreenToWorldPoint(new Vector3(0, 0, 10f));
        max = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 10f));
        // ランダムに座標を決める
        Vector3 enemyPosition = new Vector3(0, 0, 0);
        enemyPosition.x = Random.Range(min.x, max.x);
        enemyPosition.y = Random.Range(min.y, max.y);
        if(enemyPosition.x > -2f && enemyPosition.x < 2f && enemyPosition.y > -2f && enemyPosition.y < 2f)
        {
            enemyPosition.x += Random.Range(-5f, 5f);
            enemyPosition.y += Random.Range(-5f, 5f);
        }
        transform.position = enemyPosition;
        // ランダムに進行方向を定める
        Vector3 angle = new Vector3(0, 0, Random.Range(0, 360));
        enemyDirection = Quaternion.Euler(angle) * Vector3.up;
        enemyRigidbody.velocity = enemyDirection * enemySpeed;
    }
    
    void Update () {
        WallCollision();
        EnemyLookAt();
    }

    void EnemyLookAt()
    {
        // 進行方向に向かせる(2Dであることに気をつける)
        float angle = GetAngle(enemyDirection);
        transform.eulerAngles = new Vector3(0, 0, angle - 90f);
    }

    float GetAngle(Vector3 v)
    {
        float rad = Mathf.Atan2(v.y, v.x);
        return rad * Mathf.Rad2Deg;
    }

    void WallCollision()
    {
        if (transform.position.x < min.x)
        {
            Rebound(1);
        }
        if (transform.position.x > max.x)
        {
            Rebound(2);
        }
        if (transform.position.y < min.y)
        {
            Rebound(3);
        }
        if (transform.position.y > max.y)
        {
            Rebound(4);
        }
    }

    // enemyが壁に当たって跳ね返る
    void Rebound(int flag)
    {
        // 壁に当たったら位置を戻す
        Vector3 pos = transform.position;
        if (flag == 1) pos.x = min.x;
        else if (flag == 2) pos.x = max.x;
        else if (flag == 3) pos.y = min.y;
        else if (flag == 4) pos.y = max.y;
        transform.position = pos;
        // XまたはY方向の速度を逆にする
        if(flag == 1 || flag == 2) enemyDirection.x = -enemyDirection.x;
        else if(flag == 3 || flag == 4) enemyDirection.y = -enemyDirection.y;
        // 速度を更新
        enemyRigidbody.velocity = enemyDirection * enemySpeed;
    }
}

スクリーン内をランダムに動き回るようにしました

かなり力技になってしまいましたがこれで良しとしておきます(勉強します)

参考

Enemyの進行方向を決定する処理のために参考にしました

qiita.com

Enemyから弾を撃つ

以前に作ったPlayerが弾を撃つ関数を改良しました

PlayerとEnemyで共通の関数を利用することにします

public class ShotBullet : MonoBehaviour {

    public bool isShoot = true;
    public GameObject shotBullet;
    public GameObject bullet;

    IEnumerator Start()
    {
        while (isShoot)
        {
            // 弾をプレイヤーと同じ姿勢でインスタンス化
            GameObject sb = Instantiate(shotBullet, transform.position, transform.rotation);
            GameObject b = Instantiate(bullet, sb.transform);
            b.transform.position = sb.transform.position;
            b.transform.rotation = sb.transform.rotation;
            // 0.3待つ
            yield return new WaitForSeconds(0.3f);
        }
    }
}
public class Bullet : MonoBehaviour {

    public float bulletSpeed = 4f;

    void Start () {
        GetComponent<Rigidbody>().velocity = transform.up.normalized * bulletSpeed;
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}

まず、空のオブジェクト「ShotBullet」をPlayerまたはEnemyの姿勢に合わせて作成

次に「Bullet」オブジェクトを作成して「ShotBullet」の"子"とします

「Bullet」は「ShotBullet」の座標系に従って真っすぐにとんでいきます

f:id:kato_robotics:20181104042530p:plain

おわりに

敵を作成しました

次は当たり判定を付けていきます

これができればシューティングゲームにおける最低限のシステムを作ったことになります