シューティングチュートリアルをUnity5で(第09回)

第09回

プレイヤーの移動方法を変更

チュートリアルの説明文で

つまり一度移動範囲外に出た後、範囲内に強制的に移動する事になります。

とあるので「一回画面外に消えた後、強制的に戻って来る」動作をするのかと思ったけど実際の動作は消えたきり戻ってこない。 後に

プレイヤーが削除されるはずです。

と書いてあった。

  • 特記事項なし。
using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
    Spaceship spaceship;
    private Transform tran;
    private AudioSource audioSource;
    void Start() {
        spaceship = GetComponent<Spaceship>();
        tran = GetComponent<Transform>();
        audioSource = GetComponent<AudioSource> ();
        StartCoroutine("IE");
    }

    IEnumerator IE()
    {
        while (true) {
            spaceship.Shot(tran);
            audioSource.Play ();
            yield return new WaitForSeconds(spaceship.shotDelay);
        }
    }

    void Update () {
        float x = Input.GetAxisRaw("Horizontal");
        float y = Input.GetAxisRaw("Vertical");
        Vector2 direction = new Vector2(x, y).normalized;
        spaceship.Move(direction);
        Clamp();
    }

    void Clamp() {
        Vector2 min = Camera.main.ViewportToWorldPoint(new Vector2(0, 0));
        Vector2 max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1));
        Vector2 pos = tran.position;
        Debug.Log (max.x + "-" + max.y);
        pos.x = Mathf.Clamp (pos.x, min.x, max.x);
        pos.y = Mathf.Clamp (pos.y, min.y, max.y);

        transform.position = pos;
    }

    void OnTriggerEnter2D(Collider2D c)
    {
        string layerName = LayerMask.LayerToName(c.gameObject.layer);
        if (layerName == "Bullet(Enemy)") {
            Destroy (c.gameObject);
        }

        if (layerName == "Bullet(Enemy)" || layerName == "Enemy") {
            spaceship.Explosion ();
            Destroy (gameObject);
        }
    }
}
  • 特記事項なし。
using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
    Spaceship spaceship;
    private Transform tran;
    private AudioSource audioSource;
    void Start() {
        spaceship = GetComponent<Spaceship>();
        tran = GetComponent<Transform>();
        audioSource = GetComponent<AudioSource> ();
        StartCoroutine("IE");
    }

    IEnumerator IE()
    {
        while (true) {
            spaceship.Shot(tran);
            audioSource.Play ();
            yield return new WaitForSeconds(spaceship.shotDelay);
        }
    }

    void Update () {
        float x = Input.GetAxisRaw("Horizontal");
        float y = Input.GetAxisRaw("Vertical");
        Vector2 direction = new Vector2(x, y).normalized;
        Move(direction);
    }

    void Move(Vector2 direction) {
        Vector2 min = Camera.main.ViewportToWorldPoint (new Vector2 (0, 0));
        Vector2 max = Camera.main.ViewportToWorldPoint (new Vector2 (1, 1));
        Vector2 pos = transform.position;

        pos += direction * spaceship.speed * Time.deltaTime;

        pos.x = Mathf.Clamp (pos.x, min.x, max.x);
        pos.y = Mathf.Clamp (pos.y, min.y, max.y);

        transform.position = pos;
    }

    void OnTriggerEnter2D(Collider2D c)
    {
        string layerName = LayerMask.LayerToName(c.gameObject.layer);
        if (layerName == "Bullet(Enemy)") {
            Destroy (c.gameObject);
        }

        if (layerName == "Bullet(Enemy)" || layerName == "Enemy") {
            spaceship.Explosion ();
            Destroy (gameObject);
        }
    }
}

9.2 Spaceship.csとEnemy.csの修正

  • 特記事項なし
using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody2D))]
public class Spaceship : MonoBehaviour {
    public float speed; 
    public float shotDelay;
    public GameObject bullet;
    public bool canShot;
    public GameObject explosion;

    public void Explosion()
    {
        Transform tran = GetComponent<Transform> ();
        Instantiate (explosion, tran.position, tran.rotation);
    }

    public void Shot (Transform origin) {
        Instantiate(bullet, origin.position, origin.rotation);
    }
}
  • Rigidbody2を使用時に取得。
using UnityEngine;
using System.Collections;

public class Enemy : MonoBehaviour {
    Spaceship spaceship;
    private Transform tran;

    void Start () {
        spaceship = GetComponent<Spaceship> ();
        tran = GetComponent<Transform> ();
        Move (tran.up * -1);

        StartCoroutine ("IE");
    }

    IEnumerator IE() {
        if (spaceship.canShot == false) {
            yield break;
        }

        while (true) {
            for (int i = 0; i < tran.childCount; i++) {
                Transform shotPosition = transform.GetChild (i);
                spaceship.Shot (shotPosition);
            }
            yield return new WaitForSeconds (spaceship.shotDelay);
        }
    }

    public void Move(Vector2 direction)
    {
        Rigidbody2D rb2 = GetComponent<Rigidbody2D> ();
        rb2.velocity = direction * spaceship.speed;
    }

    void OnTriggerEnter2D(Collider2D c)
    {
        string layerName = LayerMask.LayerToName (c.gameObject.layer);

        if (layerName != "Bullet(Player)")
            return;

        Destroy (c.gameObject);
        spaceship.Explosion ();
        Destroy (gameObject);
    }
}

シューティングチュートリアルをUnity5で(第06〜08回)

第06回

6.2 Frontを作る

Quadを作成すると黒に近い灰色になっているのでそこにbackground-frontを乗せるとチュートリアルページの様な青い背景にならず、Playすると暗い画面になった。

f:id:shady:20150524174046j:plain f:id:shady:20150524174111j:plain Front、Middle、BackのShaderをそれぞれStandardからUnlit/Transparentに変更すると真っ暗ではなくなる。

f:id:shady:20150524174408j:plain f:id:shady:20150524174132j:plain f:id:shady:20150524174417j:plain

6.5 背景をスクロールさせる

  • Rendererを前もって取得しておく
using UnityEngine;
using System.Collections;

public class Background : MonoBehaviour {
    public float speed = 0.1f;
    private Renderer ren;

    void Start () {
        ren = GetComponent<Renderer> ();
    }
    
    // Update is called once per frame
    void Update () {
        float y = Mathf.Repeat (Time.time * speed, 1);
        Vector2 offset = new Vector2 (0, y);
        ren.sharedMaterial.SetTextureOffset ("_MainTex", offset);
    }
}

第07回

7.2 Waveを呼び出すEmitter (エミッター)を作成する

using UnityEngine;
using System.Collections;

public class Emitter : MonoBehaviour {
    public GameObject[] waves;
    private int currentWave;

    void Start () {
        StartCoroutine ("IE");
    }
    
    IEnumerator IE() {
        if (waves.Length == 0) {
            yield break;
        }

        GameObject wave = (GameObject)Instantiate (waves [currentWave], transform.position,
                              Quaternion.identity);
        wave.transform.parent = transform;
        while (wave.transform.childCount != 0) {
            yield return new WaitForEndOfFrame ();
        }

        Destroy (wave);
        if (waves.Length <= ++currentWave) {
            currentWave = 0;
        }
    }
}

第08回

8.1 BGMを付ける

Sounds/BGMにあるbgmを選択し、インスペクターの3D Soundのチェックが外れていることを確認して下さい。

  • bgm Import Settingsに3D Soundが存在しない。 f:id:shady:20150524174252j:plain

bgmファイルをシーンビューにドロップする時は背景画像上にドロップするとBackgrounds>Frontに追加されてしまうのでチュートリアル通り灰色の部分にドロップする。

8.2 プレイヤーにショット音をつける

  • AudioSourceを前もって取得しておく。
using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
    Spaceship spaceship;
    private Transform tran;
    private AudioSource audioSource;
    void Start() {
        spaceship = GetComponent<Spaceship>();
        tran = GetComponent<Transform>();
        audioSource = GetComponent<AudioSource> ();
        StartCoroutine("IE");
    }

    IEnumerator IE()
    {
        while (true) {
            spaceship.Shot(tran);
            audioSource.Play ();
            yield return new WaitForSeconds(spaceship.shotDelay);
        }
    }

    void Update () {
        float x = Input.GetAxisRaw("Horizontal");
        float y = Input.GetAxisRaw("Vertical");
        Vector2 direction = new Vector2(x, y).normalized;
        spaceship.Move(direction);
    }

    void OnTriggerEnter2D(Collider2D c)
    {
        string layerName = LayerMask.LayerToName(c.gameObject.layer);
        if (layerName == "Bullet(Enemy)") {
            Destroy (c.gameObject);
        }

        if (layerName == "Bullet(Enemy)" || layerName == "Enemy") {
            spaceship.Explosion ();
            Destroy (gameObject);
        }
    }
}

シューティングチュートリアルをUnity5で(第05回)

5.1 プレイヤーに当たり判定を付ける

  • 指定の0.02だと衝突判定を起こせないのでSizeをX,Yともに0.05にする(冒頭の注意書きがこれ。全回に書いてあるので最初気づかなかった)。 f:id:shady:20150524173601j:plain f:id:shady:20150524173609j:plain

5.2 エネミーに当たり判定を付ける

  • コライダー編集を行う時はEdit Colliderボタンを押下する。ボタン色が濃灰になると編集モード。

f:id:shady:20150524173413j:plain f:id:shady:20150524173450j:plain

スクリプトでレイヤー制御

  • 特記事項なし
using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
    Spaceship spaceship;
    private Transform tran;

    void Start() {
        spaceship = GetComponent<Spaceship>();
        tran = GetComponent<Transform>();
        StartCoroutine("IE");
    }

    IEnumerator IE()
    {
        while (true) {
            spaceship.Shot(tran);
            yield return new WaitForSeconds(spaceship.shotDelay);
        }
    }

    void Update () {
        float x = Input.GetAxisRaw("Horizontal");
        float y = Input.GetAxisRaw("Vertical");
        Vector2 direction = new Vector2(x, y).normalized;
        spaceship.Move(direction);
    }

    void OnTriggerEnter2D(Collider2D c)
    {
        string layerName = LayerMask.LayerToName(c.gameObject.layer);
        if (layerName == "Bullet(Enemy)") {
            Destroy (c.gameObject);
        }

        if (layerName == "Bullet(Enemy)" || layerName == "Enemy") {
            spaceship.Explosion ();
            Destroy (gameObject);
        }
    }
}

エネミーの当たり判定

  • 特記事項なし
using UnityEngine;
using System.Collections;

public class Enemy : MonoBehaviour {
    Spaceship spaceship;
    private Transform tran;

    void Start () {
        spaceship = GetComponent<Spaceship> ();
        tran = GetComponent<Transform> ();
        spaceship.Move (tran.up * -1);

        StartCoroutine ("IE");
    }

    IEnumerator IE() {
        if (spaceship.canShot == false) {
            yield break;
        }

        while (true) {
            for (int i = 0; i < tran.childCount; i++) {
                Transform shotPosition = transform.GetChild (i);
                spaceship.Shot (shotPosition);
            }
            yield return new WaitForSeconds (spaceship.shotDelay);
        }
    }

    void OnTriggerEnter2D(Collider2D c)
    {
        string layerName = LayerMask.LayerToName (c.gameObject.layer);

        if (layerName != "Bullet(Player)")
            return;

        Destroy (c.gameObject);
        spaceship.Explosion ();
        Destroy (gameObject);
    }
}

5.8 PlayerBulletゲームオブジェクトの削除

  • 特記事項なし
using UnityEngine;
using System.Collections;

public class Bullet : MonoBehaviour {
    public int speed = 10;
    public float lifeTime = 5;
    private Rigidbody2D rb2;

    void Start () {
        rb2 = GetComponent<Rigidbody2D>();
        rb2.velocity = transform.up * speed;
        Destroy (gameObject, lifeTime);
    }
}

シューティングチュートリアルをUnity5で(第04回)

第04回

Spaceship.csの作成

  • Rigidbody2Dを使用前に取得する(Moveメソッドはpublicなので外部から呼び出される。Startメソッドが呼ばれる前に呼び出される可能性があるのでStartメソッド内での取得は行わない)。
using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody2D))]
public class Spaceship : MonoBehaviour {
    public float speed; 
    public float shotDelay;
    public GameObject bullet;

    public void Shot (Transform origin) {
        Instantiate(bullet, origin.position, origin.rotation);
    }

    public void Move(Vector2 direction)
    {
        Rigidbody2D rb2 = GetComponent<Rigidbody2D> ();
        rb2.velocity = direction * speed; //使用
    }
}
  • Rigidbody2DとTransformを前もって取得しておく。
using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
    Spaceship spaceship;
    public float speed = 5;
    public GameObject bullet;
    private Transform tran; //宣言

    void Start() {
        tran = GetComponent<Transform>(); //取得
        StartCoroutine("IE");
    }

    IEnumerator IE()
    {
        spaceship = GetComponent<Spaceship>();
        while (true) {
            spaceship.Shot(tran);
            yield return new WaitForSeconds(spaceship.shotDelay);
        }
    }

    void Update () {
        float x = Input.GetAxisRaw("Horizontal");

        float y = Input.GetAxisRaw("Vertical");

        Vector2 direction = new Vector2(x, y).normalized;

        spaceship.Move(direction);
    }
}

spaceship取得はStartメソッド内でもコルーチン内でもOK。オリジナル重視でここでは後者。

敵の移動

  • Transformを使用前に取得する。
using UnityEngine;
using System.Collections;

public class Enemy : MonoBehaviour {
    Spaceship spaceship;
    private Transform tran; //宣言

    void Start () {
        spaceship = GetComponent<Spaceship> ();
        tran = GetComponent<Transform> (); //取得
        spaceship.Move (tran.up * -1); //使用
    }
}

弾を撃たない敵を作る

  • Rigidbody2Dを使用前に取得する。
using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody2D))]
public class Spaceship : MonoBehaviour {
    public float speed; 
    public float shotDelay;
    public GameObject bullet;
    public bool canShot;

    public void Shot (Transform origin) {
        Instantiate(bullet, origin.position, origin.rotation);
    }

    public void Move(Vector2 direction)
    {
        Rigidbody2D rb2 = GetComponent<Rigidbody2D> (); //宣言&取得
        rb2.velocity = direction * speed; //使用
    }
}
  • Transformを前もって取得しておく。
using UnityEngine;
using System.Collections;

public class Enemy : MonoBehaviour {
    Spaceship spaceship;
    private Transform tran;

    void Start () {
        spaceship = GetComponent<Spaceship> ();
        tran = GetComponent<Transform> ();
        spaceship.Move (tran.up * -1);

        StartCoroutine ("IE");
    }

    IEnumerator IE() {
        if (spaceship.canShot == false) {
            yield break;
        }

        while (true) {
            for (int i = 0; i < tran.childCount; i++) {
                Transform shotPosition = transform.GetChild (i);
                spaceship.Shot (shotPosition);
            }
            yield return new WaitForSeconds (spaceship.shotDelay);
        }
    }
}

シューティングチュートリアルをUnity5で(第03回まで)

f:id:shady:20150524135706j:plainUnity公式サイトのチュートリアルを行ってみました。全てできたのですが、Unity4用に書かれたチュートリアルなのでUnity5だと戸惑ったり書き換えが必要な箇所が結構あったのでまとめました。

このチュートリアルを始める前に

1.3 Unityを起動しよう

DLしたShootingGame.zipを解凍して開くと"Project Upgrade Required"のメッセージが出る。 f:id:shady:20150524135431j:plain →Upgradeボタンを押す

第01回

Texture Import Settings の確認

選択すべきTexture Typeは"Sprite"ではなく"Sprite (2D and UI)"となる。

f:id:shady:20150524135431j:plain

第02回

スクリプトを書く

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
    public float speed = 5;
    private Rigidbody2D rb2; //宣言

    void Start() {
        rb2 = GetComponent<Rigidbody2D>(); //取得       
    }

    // Update is called once per frame
    void Update () {
        float x = Input.GetAxisRaw("Horizontal");

        float y = Input.GetAxisRaw("Vertical");

        Vector2 direction = new Vector2(x, y).normalized;

        rb2.velocity = direction * speed; //使用
    }
}

第03回

弾を動かす

Rigidbody2Dを前もって取得しておく。

using UnityEngine;
using System.Collections;

public class Bullet : MonoBehaviour {
    public int speed = 10;
    private Rigidbody2D rb2;

    // Use this for initialization
    void Start () {
        rb2 = GetComponent<Rigidbody2D>();
        rb2.velocity = transform.up * speed;
    }
}

3.3 プレイヤーから弾を発射する

  • Transformを前もって取得する。
  • メソッド名"Start"は初期処理で使うのでコルーチン名は別の名前にする。
  • コルーチンはStartメソッド内でStartCoroutineを明示的に呼ばないと実行されない。
using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
    public float speed = 5;
    public GameObject bullet;
    private Rigidbody2D rb2;
    private Transform tran;

    void Start() {
        rb2 = GetComponent<Rigidbody2D>();
        StartCoroutine("IE");
    }

    IEnumerator IE()
    {
        while (true) {
            tran = GetComponent<Transform>();
            Instantiate(bullet, tran.position, tran.rotation);
            yield return new WaitForSeconds(0.05f);
        }
    }

    // Update is called once per frame
    void Update () {
        float x = Input.GetAxisRaw("Horizontal");

        float y = Input.GetAxisRaw("Vertical");

        Vector2 direction = new Vector2(x, y).normalized;

        rb2.velocity = direction * speed;
    }
}