altebute.hatenablog.com

犬も歩けば規格にあたる

Unity 5 日記 6 ショットを発射

もう適当にさっさと書かないと飽きるので雑に書いていく. さっさとショット発射してみたい. 敵にあたるとかそんなんどうでもいい.

Unity 5 日記 2 スクリプトの作成Unity 5 日記 3 deltaTime の適用 で作成したオブジェクトにショットの発射機能を持たせる.

作成してあった移動処理をメソッド Move に分離し, メソッド Update を以下のように書き換える.

private void Update()
{
    Move();
}

変数 float shootFreezeSystem.Collections.Generic.List<GameObject> shots を追加する.

private QuantizedTime shootFreeze;
private System.Collections.Generic.List<GameObject> shots;

ついでにメソッド Start に各々の初期化処理を追加しておく.

void Start()
{
    ...
    shootFreeze = 0;
    shots = new System.Collections.Generic.List<GameObject>();
}

はっきり言ってこの書き方は良くない. クソコードである. 関心の分離もへったくれもない. 本当なら別途ショットを管理するためのクラスを用意すべきだが, ここではとりあえず後回しにする.

Unity 5 日記 5 Prefab で書いたような感じで Prefab を作成し, Resouces フォルダに Shot という名前で適当にいれる.

そしてショットにスクリプトを追加する.

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

public class ShotBehaviorScript : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
        var x = transform.position.x;
        var y = transform.position.y;
        var z = transform.position.z;
        z += Time.deltaTime * 100;
        transform.position = new Vector3(x, y, z);
    }

    public bool IsOut()
    {
        return 32 < transform.position.z;
    }
}

メソッド Update で移動を行う. IsOut は消去判定を行うためのメソッドだ. Unity では画面外に出たことを判定するための関数があるが, ショットは画面外に出た時に消えてしまうのは困るので自分で色々判定する. ここでは本当に適当な値の比較にした.

そして自機側のスクリプトにメソッド Shoot を追加する. この名前もかなり悪い.

private void Shoot()
{
    if (0 < shootFreeze.Value)
    {
        var deltaTime = Time.deltaTime;
        shootFreeze -= deltaTime.Value;
        return;
    }

    var fire = UnityEngine.Input.GetButton("Fire1");
    if (fire)
    {
        GameObject shotPrefab = (GameObject)Resources.Load("Shot");
        var shot = Instantiate(shotPrefab, new Vector3(0,(float)_position.Y, (float)_position.X), Quaternion.identity);
        shots.Add(shot);
        shootFreeze.Value = 128;
    }
}

手元のスクリプトとブログに書いてあるスクリプトが一致していないので座標周りがおかしかったり変数名があっていなかったりするが心の目で読んで欲しい. Resouces ディレクトリに入れた Prefab は上記のような感じでインスタンス化することが出来る. 生成したショットは shots に追加する.

最後に画面外に出たショットを削除するためのメソッド RemoveShots を追加する.

void RemoveShots()
{
    for (int i = 0; i < shots.Count;)
    {
        var shot = shots[i];
        var script = shot.GetComponent<ShotBehaviorScript>();
        if (script.IsOut())
        {
            Destroy(shot);
            shots.Remove(shot);
            continue;
        }
        ++i;
    }
}

GetComponent でアタッチしたコンポーネントを取得し, メソッド IsOut で判定を行い, Destroy 関数で GameObject を削除する.

ShotBehaviorScript の中で Destroy(this) するとオブジェクト全体ではなくコンポーネント単体を削除してしまうらしい.

なんかもう記事書くのも面倒になってきた. この雑さ極まるコードを GitHub に丸上げして, コミットログにリンク張って日記にする程度でいいんじゃなかろうか.