Unity学習サイト

ホーム / カメラの動き、敵作成、弾の発射

4回目の講座です。前回までは、落下時とクリア時の処理を追加しました。
今回の講座は、このゲームでいう敵?を作っていきましょうと言いたいところですが カメラに関して何も行っていなかったので先にカメラコントロールをしていきます。

今回の講座では下のミニゲームの内容まで作ることができます。

この講座での最終完成形

カメラの追従

カメラに主人公を追従する機能をつけて広いフィールドを作っても 問題のないようにしましょう。まずは、スクリプトフォルダで右クリック→create →C#で新たなスクリプトを作って名前をCameracにしてください。
出来たらスクリプトを開いてコードを書いていきましょう。まず最初に追従する 主人公の入る箱を作ります。

GameObject player;

次に、箱に追従する主人公の情報を入れましょう。Start関数に書いていきます。 このコードはplayerという箱にヒエラルキーウィンドウの中の 主人公(tori)を探して代入するというコードになります。例えばtoriの部分を ほかのゲームオブジェクトにすればそのゲームオブジェクトをカメラが追従します。

this.player = GameObject.Find("tori");

次に、Update関数に追従するためのコードを書いていきます。下記のコードは toriのトランスフォームの値を取り出してplayerPosという箱に入れ、それを このスクリプトのついているカメラのトランスフォームに入れなおしてカメラ を動かす。というようなスクリプトになります。
むずかしいですね、すごく簡単に言うとtoriの動きをカメラが真似をしているような イメージになります。

Vector3 playerPos = this.player.transform.position;
        transform.position =
            new Vector3(playerPos.x, playerPos.y, transform.position.z);

スクリプトが書けたらアタッチしてスクリプトをヒエラルキーウィンドウにあるMainCamera にドラックアンドドロップして動きを確認しましょう。下のようにできていればOKです。

コードの役割を確認してみましょう

下記はカメラスクリプトの全文です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Camerac : MonoBehaviour
{
     GameObject player;

    void Start()
    {
        this.player = GameObject.Find("tori");
    }

    void Update()
    {
        Vector3 playerPos = this.player.transform.position;
        transform.position =
            new Vector3(playerPos.x, playerPos.y, transform.position.z);
    }
}

コードへの理解を深める応用編

下にコードへの理解が深められるプログラムを作りました。

{
      Vector3 playerPos = this.player.transform.position;
      transform.position =
          new Vector3(playerPos.x, transform.position.y, transform.position.z);
  }

上記のコードは、playerPos.yをtransform.position.yに変更してあり、Y軸に 鳥の位置が代入されていないため、カメラが上下しなくなります。カメラの上下が必要ない ゲームを作りたいときに使えますね!
下記のゲームはエンターでカメラのスクリプトが変わり動き方が変わります。 ジャンプ(スペースキー)すると違いが確認できます。

実際に動かして確認してみましょう

敵?の作成

さて、カメラの追従もできたので次は、敵?の製作をしてきましょう。 なぜ、はてなをつけているかというと。ネギまになるゲームのネギを 敵と呼んでいるのでこれは敵なのかという考えからはてなをつけています。笑 まあ、2Dアクションゲームのチュートリアルなのでとりあえず敵で行きましょう。

余談はこのぐらいにして、作っていきましょう。下のネギをnegiで保存して シーン画面に登録してください。出来たら、Add Componentを押して Physics2D→Capsule Collider 2DとRigidbody 2Dをつけてください。 転がらないように、Rigidbody 2DのConstraintsのFreezeRotationのZに チェックを入れて下さい。

学習素材の入手

下記の画像は、クリックすると自動でダウンロードされます。

Rigidbody 2D

次に、いつもの手順でネギにTagを追加してください。インスペクターウィンドウ の最上部Tagの横にあるドロップダウンをクリックしてAdd Tag→✙でnegiというTag を追加してnegiのtagに変更しておきましょう。
これでネギの下処理が終わりました。そうしたら、ネギのprefabというものを作ります。 ヒエラルキーウィンドウにあるnegiを下の画像のようにItemフォルダにドラックアンドドロップして ください。以上です。prefabというものは画像につけたデータが保持されたまま になったもので、シーン画面にあるゲームオブジェクト(ネギ)のコピーです。 何個も同じものを配置するときに作っておくと、何回もコンポーネントをつける作業が 省かれます。

prefabが作れたら最初に作ったnegiは削除してしまって大丈夫です。 ヒエラルキーウィンドウのnegiの上で右クリック→Deleteで削除できます。 ネギのprefabを三つほどシーンに配置しておきましょう。prefabは背景が グレーのほうです。

敵なので衝突したらMissシーンへ変遷するようにしましょう。鳥の衝突検知 において当たったもののTagがnegiならMissシーンをロードという文を鳥 スクリプトに追加しましょう。

if (other.gameObject.CompareTag("negi"))
        {
            SceneManager.LoadScene("Miss");
        }

ひとまずこれで敵の完成です。

実際に動かして確認してみましょう

弾の作成

敵ができたので次は弾を作っていきましょう。一緒の串になるのに捕まえられず打たれるのは よくわからない展開ですが、チュートリアルなので良しとしましょう。
さて、しかし弾といっても鳥が銃を所持しているのはさすがに変すぎるのでどうしようか 考えました。皆さんもピンと来たと思います。卵です。鳥が卵を撃ってネギを捕らえる ゲームになります。それではやっていきましょう。

学習素材の入手

下記の画像は、クリックすると自動でダウンロードされます。

Capsule Collider2D

上の卵をtamagoという名前で保存してください。そのままです。保存したら、シーン画面に登録して カプセルコライダーとリジットボディ2Dの二つのコンポーネントをつけて下さい。Add Component→Physics 2D→Capsule Collider2DとRigidbody2D
つけたカプセルコライダーのis Triggerにチェックをしましょう。また、今回卵に重力は つけませんのでRigidBody2DのBodyTypeをKinematicに変更しておきましょう。

次に、スクリプトを組んでいきましょう。
まず、卵を発射するにあたって鳥の向く方向に発射しなければならない為 鳥の向きを取得します。フィールドに鳥の入る箱を用意します。

public GameObject tori;

次にStart関数にToriゲームオブジェクトを見つけてきて箱に入れるコードを書きます。

tori = GameObject.Find("tori");

toriゲームオブジェクトを見つけてきたら次に、toriのlocalScale(画像の向き) を取り出します。(Start関数)
Vecter3 のtorimukiという箱に鳥の画像の向きの値を入れています。
以上で鳥の向きを取得することができました。

Vector3 torimuki = tori.transform.localScale;

鳥の向く方向を取得出来たら、それにスピードをかけます。鳥の向き(localScale)は1か-1ですので それに、卵の飛んでいくスピードをかければ方向とスピードが決定します。
まずは、飛んでいく向き、スピードを入れる箱をフィールドに作ります。わかりやすく mukispeedという名前にしました。

public float mukispeed;

次に、Start関数でmukispeedという箱に向きとスピードの値を入れます。鳥の向きにスピード(-0.2f)をかけています。

mukispeed=torimuki.x*-0.2f;

以上で卵の大部分の下処理が終わりました。あと少しです。
卵を生成したら飛んでいくようにするコードを書きます。卵のX軸に先ほど作った mukispeedを代入して卵を動かします。こちらは、Update関数に記述です。

transform.Translate(mukispeed, 0, 0);

以上で、卵を飛ばす下処理は完了なのですがこのままだと生成した卵がゲーム内に 残り続けてパソコンのメモリを消費して重たくなるので、一定時間たったら卵を 削除するコードを加えておきます。Update関数に下記のコードを記入しましょう。 このゲームオブジェクトを0.5フレームで削除するというコードになります。

Destroy(this.gameObject, 0.5f);

以上で卵の発射に関する下処理はすべて完了です。次に鳥(発射する側)が 卵を発射できるようにしてきましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tamago : MonoBehaviour
{
    public GameObject tori;
    public float mukispeed;
    // Start is called before the first frame update
    void Start()
    {
      tori = GameObject.Find("tori");
      Vector3 torimuki = tori.transform.localScale;
      mukispeed=torimuki.x*-0.2f;

    }

    // Update is called once per frame
    void Update()
    {
        transform.Translate(mukispeed, 0, 0);
        Destroy(this.gameObject, 0.5f);
    }
}

鳥側の処理

卵の処理ができたら発射の仕方についてやっていきましょう。まずは、 Toriスクリプトのフィールドに卵オブジェクトのprefabが入る箱を用意します。

public GameObject tamago;

先ほど作った箱はPublicで作ったのでヒエラルキーウィンドウに卵prefab が入る 箱が出来ていますのでコードをアタッチして卵prefabを箱に入れましょう。 卵purefabをドラックアンドドロップです。

箱に卵purefabを入れたらキーボードのCで卵を発射できるようにします。 Update関数に下記のコードを追加します。キーボードのCが押されたら 先ほど入れた卵purefabを鳥のいる場所から発射するというコードになります。

if (Input.GetKeyDown(KeyCode.C))
        {
            Instantiate(tamago, transform.position, Quaternion.identity);
        }

以上で、卵の発射ができるようになりました!下でコードの役割を確認しましょう。

実際に動かして確認してみましょう

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Tori : MonoBehaviour
{
    Rigidbody2D rigid2D;
    float maxWalkSpeed = 2.0f;
    float walkForce = 30.0f;
    float jumpForce = 5.0f;
    public float defScalex;
    public bool jump = false;
    public GameObject tamago;

    void Start()
    {
        this.rigid2D = GetComponent();
        this.defScalex = transform.localScale.x;
    }

    void Update()
    {
        //左右移動
        int key = 0;
        if (Input.GetKey(KeyCode.RightArrow))
            key = 1;
        if (Input.GetKey(KeyCode.LeftArrow))
            key = -1;
        //プレイやーの速度
        float speedx = Mathf.Abs(this.rigid2D.velocity.x);
        //スピードで制限
        if (speedx < this.maxWalkSpeed)
        {
            this.rigid2D.AddForce(transform.right * key * this.walkForce);
        }
        //移動時の反転
        if (key != 0)
        {
            transform.localScale = new Vector3(-1 * key * defScalex, transform.localScale.y, 1);
        }
        //ジャンプ
        if (Input.GetKeyDown(KeyCode.Space) && !jump)
        {
            this.rigid2D.AddForce(transform.up * this.jumpForce, ForceMode2D.Impulse);
            jump = true;
        }
        //落下の判定
        if (transform.position.y < -20)
        {
            SceneManager.LoadScene("Miss");
        }
        //卵発射
        if (Input.GetKeyDown(KeyCode.C))
        {
            Instantiate(tamago, transform.position, Quaternion.identity);
        }
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        //二段飛び防止
        if (other.gameObject.CompareTag("Ground"))
        {
            jump = false;
            print("グランドに接地したよ");
        }
        //Goal用
        if (other.gameObject.CompareTag("Goal"))
        {
            SceneManager.LoadScene("Clear");
            print("Goalしたよ");
        }
        //ネギ衝突
        if (other.gameObject.CompareTag("negi"))
        {
            SceneManager.LoadScene("Miss");
        }
    }
}

ネギの回収、卵の削除

だいぶゲームらしくなってきましたね。しかし、卵を撃っても地面を通り抜けたり ネギをすり抜けたりしますよね。それらを、修正していきましょう。

まずは、卵がネギに当たったらネギが回収される(消える)ようにしましょう。 Tamagoスクリプトにvoid OnTriggerEnter2D(Collider2D other)関数を作りましょう。 その中に、If文でnegiのtagに衝突したらぶつかったネギと卵を消すコードを書きましょう。

void OnTriggerEnter2D(Collider2D other)
    {
        if(other.gameObject.CompareTag("negi")){
            Destroy(this.gameObject);
            Destroy(other.gameObject);
        }
    }

次は、卵が地面に衝突したら卵が消えるコードを書きます。先ほど追加した if文の下に下記のコードを追加します。構造はネギが消えるコードと同じです。

if (other.gameObject.CompareTag("Ground"))
        {
            Destroy(this.gameObject);
        }

以上で変な現象たちは無くなりました。下でコードの確認をしてみましょう。

実際に動かして確認してみましょう

これで今回の講座は終わりです!! お疲れ様でした!Tamagoスクリプトの完成形を貼っておきます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tamago : MonoBehaviour
{
    public GameObject tori;
    public float mukispeed;
    // Start is called before the first frame update
    void Start()
    {
      tori = GameObject.Find("tori");
      Vector3 torimuki = tori.transform.localScale;
      mukispeed=torimuki.x*-0.2f;

    }

    // Update is called once per frame
    void Update()
    {
        transform.Translate(mukispeed, 0, 0);
        Destroy(this.gameObject, 0.5f);
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.gameObject.CompareTag("negi"))
        {
            Destroy(this.gameObject);
            Destroy(other.gameObject);
        }
        if (other.gameObject.CompareTag("Ground"))
        {
            Destroy(this.gameObject);
        }

    }
}

次の講座へ

ホームへ