Skip to content

第7回 敵が現れる ​

この回でつくるもの:画面の右の外から、敵が一定の時間ごとに出てきて、左へ進んでくるようにします。出てくる高さは毎回ランダムです。

この回で学ぶこと ​

  • 自機と同じ「親+子(モデル)」の形で敵を作る
  • 画面の外に出たオブジェクトを消す
  • コルーチン(IEnumerator、yield return、WaitForSeconds)で「待ってから動く」処理を書く
  • while (true) でくり返す
  • Random.Range でランダムな数を作る

前回までのふりかえり ​

前回は、Particle System で遠くの星と近くの星を作り、速さを変えて流しました。岩も BackgroundScroller で流れています。 宇宙を飛んでいる感じが出てきましたね。 今回は、いよいよ敵を出します。

1. 敵を作る ​

1-1. 親のオブジェクトを作る ​

自機と同じように、「親(空のオブジェクト)」+「子(見た目のモデル)」の2段で作ります。

  1. Hierarchy の何もないところを右クリックして Create Empty を選びます。
  2. 名前を Enemy_Straight にします(まっすぐ進む敵、という意味です)。
  3. Inspector の Transform で Position を (5, 0, 0) にします(作業しやすい場所に置いておきます)。
  4. Rotation が (0, 0, 0)、Scale が (1, 1, 1) であることを確かめます。

1-2. 見た目のモデルを入れる ​

  1. Project ウィンドウで Assets/ThirdParty/KenneySpaceKit を開きます。
  2. craft_racer を、Hierarchy の Enemy_Straight の上へドラッグ&ドロップします。
  3. Enemy_Straight の子になったモデルの名前を Model に変えます。
  4. Model を選び、Position を (0, 0, 0) にします。
  5. Rotation の Y を 90 か -90 にして、機首が 左(-X) を向くようにします。
  6. Scale を調整して、横幅が自機と同じくらい(約1.5)になるようにします。

ヒント

ファイル名がちがったら、Project ウィンドウのプレビューを見て好きなモデルを選んでOKです。自機とは形や色がちがうものを選ぶと、見分けやすくなります。

注意

向きを直すのは 子の Model の Rotation です。親の Enemy_Straight の Rotation は (0, 0, 0) のままにしておきます。親を回すと、スクリプトで動かしたときに思わぬ方向へ進むことがあります。

1-3. 色を変える(好みで) ​

  1. Project ウィンドウで Assets/_Game/Materials を開きます。
  2. 右クリックして Create > Material を選び、名前を Mat_Enemy にします。
  3. Base Map の色を赤やむらさきなど、敵らしい色にします。
  4. Mat_Enemy を Scene ビューの敵のモデルへドラッグ&ドロップします。
  5. Ctrl+S(Macは Cmd+S)でシーンを保存します。

2. Enemy スクリプト ​

2-1. スクリプトを作る ​

  1. Project ウィンドウで Assets/_Game/Scripts を開きます。
  2. 右クリックして Create > Scripting > MonoBehaviour Script を選びます。
  3. 名前を Enemy にして Enter を押します。
  4. ダブルクリックしてエディタで開きます。

2-2. コードを書く ​

中身をすべて消して、次のコードを書きます。

csharp
using UnityEngine;

// 敵の基本(移動)
public class Enemy : MonoBehaviour
{
    public float speed = 3f;              // 左へ進む速さ

    void Update()
    {
        transform.Translate(Vector3.left * speed * Time.deltaTime, Space.World);

        // 画面の左に出たら消す
        if (transform.position.x < -12f)
        {
            Destroy(gameObject);
        }
    }
}

書けたら保存して Unity にもどります。

2-3. コードの解説 ​

行意味
public float speed = 3f;左へ進む速さ。1秒に3進む
transform.Translate(Vector3.left * ..., Space.World);世界の左へ動かす(前回の BackgroundScroller と同じ)
if (transform.position.x < -12f)もし x が -12 より左になったら
Destroy(gameObject);自分自身をすぐに消す
  • 画面の左はしは約 -8.9 です。-12 はそれより外なので、プレイヤーには消える瞬間が見えません。
  • 消さないと、画面の外にいつまでも敵がたまっていき、ゲームが重くなります。弾を2秒で消したのと同じ理由です。
  • 第5回の Destroy(gameObject, lifeTime) は「時間がたったら消す」でしたが、今回は数字がないので「すぐに消す」になります。

2-4. 敵に付けて試す ​

  1. Hierarchy で Enemy_Straight(親)を選びます。
  2. Add Component をクリックして、Enemy を検索して付けます。
  3. ▶ Play ボタンを押します。

敵が左へ進んでいき、画面の外へ出たあとで Hierarchy から Enemy_Straight が消えればOKです。確かめたら ▶ を押して止めます。

3. プレハブにする ​

3-1. プレハブを作る ​

敵もたくさん出したいので、弾と同じようにプレハブにします。

  1. Project ウィンドウで Assets/_Game/Prefabs を開きます。
  2. Hierarchy の Enemy_Straight を、Prefabs フォルダへドラッグ&ドロップします。
  3. Project に Enemy_Straight プレハブができたことを確かめます。

3-2. シーンの敵を消す ​

  1. Hierarchy の Enemy_Straight を選びます。
  2. Delete キー(Macは Cmd+Delete)を押して消します。
  3. Ctrl+S(Macは Cmd+S)でシーンを保存します。

ヒント

プレハブをあとで直したいときは、Project の Enemy_Straight をダブルクリックします。プレハブモード(プレハブだけを編集する画面)になります。終わったら、Hierarchy の左上の <(矢印)を押してシーンにもどります。

4. EnemySpawner(敵を出す係) ​

4-1. コルーチンとは ​

「1.5秒待つ → 敵を出す → また1.5秒待つ → 敵を出す…」という処理を作りたいとします。 Update は毎フレーム呼ばれるので、「ここで1.5秒待って」と書くことができません。

そこで使うのが コルーチン です。コルーチンは「とちゅうで一時停止して、時間がたったら続きから動く」ことができる特別な関数です。

csharp
IEnumerator SpawnLoop()
{
    while (true)
    {
        yield return new WaitForSeconds(interval);   // ここで interval 秒、一時停止
        // 時間がたったら、ここから続きが動く
    }
}
書き方意味
IEnumerator「これはコルーチンです」というしるし(ふつうの関数の void の代わり)
yield return new WaitForSeconds(秒数);指定した秒数だけ一時停止する
StartCoroutine(SpawnLoop());コルーチンを動かし始める
while (true) { }{ } の中をずっとくり返す

while (条件) は「条件が正しいあいだ、くり返す」という意味です。true(いつでも正しい)と書くと、ゲームが終わるまでずっとくり返します。

よくあるまちがい

while (true) の中に yield return を書き忘れると、一時停止せずに一瞬で無限にくり返してしまい、Unity が固まって動かなくなります。while (true) を書いたら、中に yield return があるか必ず確かめましょう。もし固まったら、先生に知らせてください。

4-2. スクリプトを作る ​

  1. Project ウィンドウで Assets/_Game/Scripts を開きます。
  2. 右クリックして Create > Scripting > MonoBehaviour Script を選びます。
  3. 名前を EnemySpawner にして Enter を押します。
  4. ダブルクリックしてエディタで開き、中身をすべて消して次のコードを書きます。
csharp
using System.Collections;
using UnityEngine;

// 敵を一定時間ごとに出す
public class EnemySpawner : MonoBehaviour
{
    public GameObject enemyPrefab;      // 出す敵
    public float interval = 1.5f;       // 出す間隔(秒)
    public float minY = -4f;            // 出す高さの範囲
    public float maxY = 4f;

    void Start()
    {
        StartCoroutine(SpawnLoop());
    }

    IEnumerator SpawnLoop()
    {
        while (true)
        {
            yield return new WaitForSeconds(interval);

            // ランダムに高さを決める
            float y = Random.Range(minY, maxY);

            Vector3 pos = new Vector3(transform.position.x, y, 0f);
            Instantiate(enemyPrefab, pos, Quaternion.identity);
        }
    }
}

書けたら保存して Unity にもどります。

4-3. コードの解説 ​

行意味
using System.Collections;IEnumerator を使うために必要な1行
public GameObject enemyPrefab;出す敵のプレハブを入れる箱
public float interval = 1.5f;敵を出す間隔(秒)
public float minY / maxY敵を出す高さの、いちばん下といちばん上
StartCoroutine(SpawnLoop());ゲームが始まったら、コルーチンを動かし始める
Random.Range(minY, maxY)-4 から 4 のあいだの、ランダムな数を1つ作る
new Vector3(transform.position.x, y, 0f)x は EnemySpawner の位置、y はランダム、z は 0
Instantiate(enemyPrefab, pos, Quaternion.identity);その場所に敵を作る(第5回の弾と同じ)
  • Random.Range は、使うたびにちがう数を返します。だから敵が出てくる高さが毎回変わります。
  • x に transform.position.x を使っているので、EnemySpawner を置いた場所の x から敵が出てきます。

先生へ

Random.Range は、float(小数)を渡すと最大値もふくむ範囲の小数を、int(整数)を渡すと最大値を ふくまない 整数を返します。第13回で配列から敵を選ぶときに整数版を使うので、そのときに説明するとスムーズです。

5. EnemySpawner を置く ​

5-1. 置き場所を作る ​

  1. Hierarchy の何もないところを右クリックして Create Empty を選びます。
  2. 名前を EnemySpawner にします。
  3. Inspector の Transform で Position を (11, 0, 0) にします。

x = 11 は、画面の右はし(約 8.9)より外です。こうすると、敵が画面の外から入ってくるように見えます。

5-2. スクリプトを付けてプレハブを入れる ​

  1. Hierarchy で EnemySpawner を選んだまま、Add Component をクリックします。
  2. EnemySpawner を検索して付けます。
  3. Project の Prefabs フォルダにある Enemy_Straight を、Inspector の Enemy Prefab の欄へドラッグ&ドロップします。
  4. Interval が 1.5、Min Y が -4、Max Y が 4 になっていることを確かめます。
  5. Ctrl+S(Macは Cmd+S)でシーンを保存します。

注意

Enemy Prefab には、必ず Project の Prefabs フォルダの Enemy_Straight を入れます。シーンの敵はもう消してあるので、Hierarchy にはありません。

5-3. 動作確認 ​

▶ Play ボタンを押して、次のようになればOKです。

  • 1.5秒ごとに、画面の右の外から敵が出てくる
  • 敵が出てくる高さが毎回ちがう
  • 敵が左へ進み、画面の外へ出ると Hierarchy から消える(Enemy_Straight(Clone) が増えたり減ったりする)

まだ当たり判定がないので、弾を当てても敵は倒れず、自機にぶつかってもすり抜けます。次の回で作ります。

チャレンジ課題 ​

  • Interval を 0.5 にして、敵がたくさん出る「はげしいステージ」にしてみよう
  • プレハブの Enemy_Straight を開き、Speed を変えて、速い敵・おそい敵を試してみよう
  • Min Y と Max Y を変えて、画面の上半分だけから敵が出るようにしてみよう
  • ヒント:Random.Range を使って、敵の速さもランダムにできるかな?(Enemy の Start で speed = Random.Range(2f, 5f); など)

つまずきポイント ​

こんなときはここを確認
敵が出てこないEnemySpawner に EnemySpawner スクリプトが付いているか。Enemy Prefab の欄が空になっていないか
敵が右へ進む・上下に進む親の Enemy_Straight の Rotation が (0, 0, 0) か。Vector3.left と書いたか
敵がうしろ向き(機首が右)子の Model の Rotation Y を 90 と -90 で入れかえてみる
Unity が固まったwhile (true) の中に yield return new WaitForSeconds(interval); を書いたか
IEnumerator に赤い波線が出る1行目に using System.Collections; を書いたか
敵が画面の外へ出ても消えないif (transform.position.x < -12f) の - を忘れていないか

まとめ ​

  • 敵も「親+子(モデル)」で作り、向きは子の Rotation で直す
  • 画面の外へ出たものは Destroy で消して、ゲームを軽く保つ
  • コルーチンを使うと「待ってから動く」をくり返す処理が書ける
  • Random.Range でランダムな数を作ると、毎回ちがう遊びになる