小白贪狼做塔防(3)

现在我们来探讨怪物的相关事宜:
首先我们给怪物加一个EnemyContrl脚本,用来储存怪物的各种属性以及寻路,各种动画。


小白贪狼做塔防(3)_第1张图片
怪物身上的组件以及脚本设置

话不多说,贴上代码先:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;

public class EnemyContrl : MonoBehaviour

{
    /// 
    /// 敌人的伤害值
    /// 
    public float Destruction;
    /// 
    /// 子弹的伤害
    /// 
    private float Damage;
    /// 
    /// 怪物血量
    /// 
    public float Blood = 100f;
    private float b ;
    /// 
    /// 怪物要到达的终点
    /// 
    public GameObject Pos;
    /// 
    /// 自动寻路组件
    /// 
    private NavMeshAgent agt;
    /// 
    /// 定义动画控制器
    /// 
    private Animator Ani;
    /// 
    /// 死亡后销毁时间
    /// 
    private float DestryTime = 3f;
    /// 
    /// 计时器
    /// 
    private float Timer = 0;

    private Slider sd;
    void Awake()
    {
        sd = transform.GetChild(3).GetChild(0).GetComponent();
        sd.value = sd.maxValue = 1;
        b = Blood;
    }
    void Start()
    {
        //获取自动寻路组件
        agt = this.GetComponent();
        //获取动画控制组件
        Ani = this.GetComponent();
        //将终点位置传递进去
        agt.SetDestination(Pos.transform.position);
    }

    // Update is called once per framea
    void Update()
    {
        transform.GetChild(3).transform.forward = Camera.main.transform.forward;
        //监测生命值
        EnemyDead(Blood);
        //检测是否到达水晶
        Attack();
    }
    public void EnemyHurt(float Damage)
    {
        Blood -= Damage;
         
        sd.value = Blood /b;
        
    }
    public void EnemyDead(float Blood)
    {
        if (Blood <= 0)
        {
            this.gameObject.GetComponent().enabled = false;
            Destroy(this.gameObject.GetComponent());
            //杀怪物获得金币
            GameData.Instance.money += 10;
            Ani.SetBool("Dead", true);
            Ani.SetBool("Attack", false);
            //agt.SetDestination(this.transform.position);
            this.gameObject.GetComponent().enabled = false;
            Timer += Time.deltaTime;
            if (Timer >= DestryTime) {
                Destroy(this.gameObject);
            }
        }
        else
        {

        }
    }

    public void Attack()
    {
        if (Vector3.Distance(this.transform.position, Pos.transform.position) <= 3.5)
        {
            Ani.SetBool("Attack", true);
        }
    }
}

有了这些还不够,我们还需要创建一个怪物生成点 (一个空物体即可)
挂载EnemyCreatePos脚本,这里尚未使用对象池技术,想要使用该技术的请到我之前发的文章里找找灵感。
链接:http://www.jianshu.com/p/18950e18ea75

再编写生成脚本时,我们要提前想好自己需要几种不同种类的怪物,这里的不同种类不是指外形的不同,而是比如,地面怪物,空中怪物,甚至物理怪物或魔法怪物,我暂时只分出地面怪物,空中怪物两大类。
代码如下:

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

public class EnemyCreatePos : MonoBehaviour
{
    //public float CreateSpeed = 2;
    /// 
    /// 波数
    /// 
    public int boshu = 10;
    /// 
    /// 每波间隔
    /// 
    public float bowait = 5;
    /// 
    /// 每波怪数量
    /// 
    public int bonum = 10;
    /// 
    /// 每个怪间隔
    /// 
    public float numwait = 2;
    /// 
    /// 第几波
    /// 
    private int boNO;
    /// 
    /// 每波第几个
    /// 
    private int numNO;

    private string str;
    //void Start () {
    //    StartCoroutine("CreateEnemy");
    //}
    //public GameObject enemyPrefabHyp;
    // Use this for initialization
    void Start()
    {
        StartCoroutine(Test02(boshu));
    }

    // Update is called once per frame
    void Update()
    {

    }
    //num:一共产生多少波怪
    IEnumerator Test02(int num)
    {
        boNO = 0;
        while (boNO < num)
        {
            //Camera.main.transform.GetComponent().weather = boNO % 3;
            
            GameObject.Find("Weather").transform.GetComponent().weather = boNO / 3;
            GameObject.Find("Weather").transform.GetComponent().Change();
            boNO++;
            yield return StartCoroutine(Test01(bonum));
            Debug.Log("第" + boNO + "波怪产生结束");
            //每波怪产生的时间差
            yield return new WaitForSeconds(bowait);
            Debug.Log("注意第" + (boNO + 1) + "波怪即将产生");
        }
        Debug.Log("GameOver");
    }
    //number:每波怪的数量
    IEnumerator Test01(int number)
    {
        numNO = 0;
        while (numNO < number)
        {
            numNO++;
            //每个怪产生的时间差
            if (boNO > 5)
                yield return new WaitForSeconds(numwait / 2);
            else
                yield return new WaitForSeconds(numwait);
            string a = ChooseEnemy(boNO,numNO);
            //GameObject enemy = (GameObject)Resources.Load("Prefabs_Enemy/mon_goblinWizard");
            GameObject enemy = (GameObject)Resources.Load("Prefabs_Enemy/"+a);
            enemy.GetComponent().Pos = GameObject.FindGameObjectWithTag("WayPos");
            //print(enemy.GetComponent().Pos.name);
            GameObject o;
            //如果在飞行怪,则拔高5
            if (enemy.tag == "FlyEnemy")
            {
                o = Instantiate(enemy, transform.position + Vector3.up * 5, transform.rotation);
            }
            else
                o =  Instantiate(enemy,transform.position,transform.rotation);
            o.transform.parent = transform;

        }

    }
    /// 
    /// 选择怪物种类
    /// 
    /// 波次
    /// 怪次
    /// 
    string ChooseEnemy(int boNO, int numNO)
    {

        switch(boNO % 3)
        {

            case 1:
                {
                    if (numNO < 8)
                    {
                        str = "AmurTiger_01";
                    }
                    else if (numNO < 10 && numNO >= 8)
                    {
                        str = "AmurTiger_02";
                    }
                    else
                    {
                        str = "AmurTiger_03";
                    }
                    break;
                }
            case 2:
                {
                    if (numNO < 8)
                    {
                        str = "GiantBat";
                    }
                    else if (numNO < 10 && numNO >= 8)
                    {
                        str = "GiantBat_2";
                    }
                    else
                    {
                        str = "GiantBat_3";
                    }
                    break;
                }
            case 3:
                {
                    if (numNO < 8)
                    {
                        print("3-1");
                        str = "Manticore_01";
                    }
                    else if (numNO < 10 && numNO >= 8)
                    {
                        print("3-2");
                        str = "Manticore_02";
                    }
                    else
                    {
                        str = "Manticore_03";
                    }
                    break;
                }
            case 0:
                {
                    if (numNO < 4)
                    {
                        str = "GiantBat_2";
                    }
                    else if (numNO < 7 && numNO >= 4)
                    {
                        str = "AmurTiger_02";
                    }
                    else if (numNO <= 10 && numNO >= 7)
                    {
                        str = "Manticore_02";
                    }
                    break;
                }
        }
        return str;
    }
        
    //IEnumerator CreateEnemy() {
    //    while (true) {       
    //        yield return new WaitForSeconds(CreateSpeed);
    //        GameObject enemy = (GameObject)Resources.Load("Prefabs_Enemy/mon_goblinWizard");        
    //        enemy.GetComponent().Pos = GameObject.FindGameObjectWithTag("WayPos");
    //        Instantiate(enemy);
    //    }     
    //}
}

很明显,我设置了很多public,这是方便在外部调试。首先我的想法是将怪物分成n个波次,每波m个怪物,后期可以选择关卡难度时可以改变,甚至可以每波数量递增。其次我们需要将自己需要的怪物名字写成何种形式,或枚举,或分支,总之可以在生成怪时可以控制每次生成的怪物是哪一个。最后,我们对脚本进行微调,如:若是飞行怪则出生高度拔高x单位,或为每一波怪物来临之前加上一个提示等等,随你喜欢。
当然,我们要在怪物的攻击动画中添加时间,在怪物攻击“水晶”或者“萝卜”的时候,扣除水晶一定血量,本游戏采取积分制,但是目前所有怪物死亡后加的分数相同,不便于分出高下,所以我便加了一个判断,假如怪物是被防御塔打死则加10分,被水晶打死则不得分,甚至扣分。
怪物生成逻辑就先告一段落,日后若有优化会开新篇,下一篇我们来探讨防御塔对怪物的检测以及各种子弹的逻辑。

你可能感兴趣的:(小白贪狼做塔防(3))