Unity C#で作ってみたタワーディフェンス基礎設計

IT

記録として。

スポンサーリンク

敵を動かす

近づいた敵を攻撃する

towerformap1
タワーはコライダーの広さの射程範囲を持っており、射程内に入った敵を攻撃して、HPが0になると敵が消滅します。
このタワーはプレハブ化し、複製できるようにしておきます。

タワーのほうのコードは以下の通りですが仮。一度攻撃モードに入ると、狙った敵が射程外に出てもそのまま攻撃する設定になっています。

//Unity C#
public class Tower : MonoBehaviour
{
    //射程内に敵がいる場合True
    public bool attacking = false;
    //攻撃中はTrue
    public bool attack = false;
    //既定の量溜まるたび攻撃
    public int attackingCount;
    //攻撃力
    float strength;

    void Start()
    {
        //このタワーの攻撃力
        strength = 30;
    }

    void FixedUpdate()
    {
        //射程内に敵がいる場合継続して実行
        if (attacking)
        {
            attackingCount++;
            if (attackingCount == 50)
            {
                //攻撃トリガーON
                attack = true;
                attacking = false;
                attackingCount = 0;
            }
        }

    }

    //射程内に敵が入ってる間の挙動
    void OnTriggerStay2D(Collider2D enemy)
    {
        attacking = true;
        if (attack)
        {
            enemy.gameObject.GetComponent().enemyHP -= strength;
            //攻撃エフェクトON
            enemy.gameObject.GetComponent().enemyDamaged = true;

            //攻撃した敵のHPが0になった場合
            if (enemy.gameObject.GetComponent().enemyHP <= 0)
            {
                enemy.gameObject.GetComponent().enemyDead = true;
                attacking = false;
            }
            attack = false;
        }
    }
}

移動する敵のほうでは、攻撃を喰らった時にエフェクトするのと、HPが0になった時に消滅する動作を実装します。gifでは鳴ってませんが音も出してます。

//Unity C#
public class EnemyMovement : MonoBehaviour
{
  (略)
    //死亡フラグ
    public bool enemyDead = false;
    public int deathCount = 10;
    //ダメージエフェクト
    public bool enemyDamaged;
    public int damageCount = 10;
    public AudioClip dmg;

    void Start()
    {
     (略)
        //ステータス
        enemyHP = 50;
    }

      //死亡確認
        if(enemyDead)
        {

            deathCount--;
            this.gameObject.GetComponent().color -= new Color(0, 0, 0, 0.1f);
            if (deathCount < 0)
            {
                Destroy(this);
            }

        }

     (略)

        //ダメージ
        if (enemyDamaged)
        {
            damageCount--;
            switch (damageCount)
            {
                case 9:
                    GetComponent().PlayOneShot(dmg);
                    this.transform.Translate(0.05f, 0.05f, 0);
                    this.gameObject.GetComponent().color -= new Color(0, 0.1f, 0.1f, 0.1f);
                    break;
                case 8:
                    this.transform.Translate(-0.05f, -0.05f, 0);
                    this.gameObject.GetComponent().color -= new Color(0, 0.1f, 0.1f, 0.1f);
                    break;
                case 7:
                    this.transform.Translate(-0.05f, -0.05f, 0);
                    this.gameObject.GetComponent().color -= new Color(0, 0.1f, 0.1f, 0.1f);
                    break;
                case 6:
                    this.transform.Translate(0.05f, 0.05f, 0);
                    this.gameObject.GetComponent().color -= new Color(0, 0.1f, 0.1f, 0.1f);
                    break;
                case 5:
                    this.transform.Translate(-0.05f, 0.05f, 0);
                    this.gameObject.GetComponent().color -= new Color(0, 0.1f, 0.1f, 0.1f);
                    break;
                case 4:
                    this.transform.Translate(0.05f, -0.05f, 0);
                    this.gameObject.GetComponent().color += new Color(0, 0.1f, 0.1f, 0.1f);
                    break;
                case 3:
                    this.transform.Translate(0.05f, -0.05f, 0);
                    this.gameObject.GetComponent().color += new Color(0, 0.1f, 0.1f, 0.1f);
                    break;
                case 2:
                    this.transform.Translate(-0.05f, 0.05f, 0);
                    this.gameObject.GetComponent().color += new Color(0, 0.1f, 0.1f, 0.1f);
                    break;
                case 1:
                    this.gameObject.GetComponent().color += new Color(0, 0.1f, 0.1f, 0.1f);
                    break;
                case 0:
                    this.gameObject.GetComponent().color += new Color(0, 0.1f, 0.1f, 0.1f);
                    damageCount = 10;
                    enemyDamaged = false;
                    break;
            }

        }

}

タワーをドラッグして追加する

towerformap2
さらにタワーをドラッグで追加できるようにします。
この状態だと左下のタワーがマップ上に単に移動してるだけですが、
①ドロップ時にマップに接触していればプレハブを作成したい②ドラッグしたタワーは元の位置に戻したい ので、ドラッグするタワーのほうのコードは以下のようになります。
//Unity C#
public class TowerDrag : MonoBehaviour
{
    //ドラッグしている間はON
    public bool boxFlag;
    //マップに接地している間はON
    public bool mapFlag;
    //定位置
    Vector3 myPosition;
    //プレハブ
    public GameObject tower;
    public Vector3 mapPosition;

    void Start()
    {
        //戻る位置
        myPosition = this.transform.position;
    }

    public void MouseDrag()
    {
        (略)
    }

    void OnMouseUp()
    {
        //ドラッグ終了、吸い込んでよし
        boxFlag = false;    
        MakeTower();
    }

    //プレハブ作成
    public void MakeTower()
    {
    if (mapFlag)
    {
        GameObject newTower = Instantiate(tower) as GameObject;
        newTower.transform.position = mapPosition;
    }
        //初期位置に帰る
        this.transform.position = myPosition;
    }

}

これに対し、タワーを置けるマップは以下のようなコードになります。

//Unity C#
public class Floor : MonoBehaviour
{

    //トリガーに他のオブジェクトが接している間は処理を繰り返し実行
    void OnTriggerStay2D(Collider2D tower)
    {
        //ドラッグしてる間は
        tower.GetComponent().mapPosition = this.transform.position;
        if (tower.GetComponent().boxFlag)
        {
            this.GetComponent().color = new Color(1f, 0.7f, 0.5f, 1f);
            tower.GetComponent().mapFlag = true;
        }
    }

    void OnTriggerExit2D(Collider2D tower)
    {
        this.GetComponent().color = Color.white;
        tower.GetComponent().mapFlag = false;
    }
}
towerformap3
褒められたコードではないものの、タワーディフェンスっぽい動きはするようになったのでとりあえず満足。
ここからコストを設定したりタワーの種類を増やしたり、よりゲームらしく動かすための実装をしていきます。
やりたいことから逆引きするUNITYの使い方まとめ
Unityをやりたいことから学習していけるよう、機能・用途別にまとめたページです。C#の命令別の逆引きは現時点で作っていません。2019の時期に書き始めているので、それより前のバージョンについては言及しません。

コメント