美文网首页unity3D技术分享
小白贪狼做塔防(3)

小白贪狼做塔防(3)

作者: 貪狼大人 | 来源:发表于2017-10-20 14:23 被阅读0次

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


怪物身上的组件以及脚本设置

话不多说,贴上代码先:

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

public class EnemyContrl : MonoBehaviour

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

    private Slider sd;
    void Awake()
    {
        sd = transform.GetChild(3).GetChild(0).GetComponent<Slider>();
        sd.value = sd.maxValue = 1;
        b = Blood;
    }
    void Start()
    {
        //获取自动寻路组件
        agt = this.GetComponent<NavMeshAgent>();
        //获取动画控制组件
        Ani = this.GetComponent<Animator>();
        //将终点位置传递进去
        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<Collider>().enabled = false;
            Destroy(this.gameObject.GetComponent<Rigidbody>());
            //杀怪物获得金币
            GameData.Instance.money += 10;
            Ani.SetBool("Dead", true);
            Ani.SetBool("Attack", false);
            //agt.SetDestination(this.transform.position);
            this.gameObject.GetComponent<NavMeshAgent>().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;
    /// <summary>
    /// 波数
    /// </summary>
    public int boshu = 10;
    /// <summary>
    /// 每波间隔
    /// </summary>
    public float bowait = 5;
    /// <summary>
    /// 每波怪数量
    /// </summary>
    public int bonum = 10;
    /// <summary>
    /// 每个怪间隔
    /// </summary>
    public float numwait = 2;
    /// <summary>
    /// 第几波
    /// </summary>
    private int boNO;
    /// <summary>
    /// 每波第几个
    /// </summary>
    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<WeatherController>().weather = boNO % 3;
            
            GameObject.Find("Weather").transform.GetComponent<WeatherController>().weather = boNO / 3;
            GameObject.Find("Weather").transform.GetComponent<WeatherController>().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<EnemyContrl>().Pos = GameObject.FindGameObjectWithTag("WayPos");
            //print(enemy.GetComponent<EnemyContrl>().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;

        }

    }
    /// <summary>
    /// 选择怪物种类
    /// </summary>
    /// <param name="boNO"></param>波次
    /// <param name="numNO"></param>怪次
    /// <returns></returns>
    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<EnemyContrl>().Pos = GameObject.FindGameObjectWithTag("WayPos");
    //        Instantiate(enemy);
    //    }     
    //}
}

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

相关文章

  • 小白贪狼做塔防(3)

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

  • 小白贪狼做塔防(5)

    下面,我们为游戏加一点变数——天气最初的设想为晴天时,火焰·炮弹防御塔正常运行,弩箭·激光武器威力加1/2,冰塔减...

  • 小白贪狼做塔防(4)

    现在呢我们来搞一下防御塔对怪物的检测逻辑。首先呢,我想到了触发器检测,并配以一条列表储存在该防御塔射程内的所有敌人...

  • 小白贪狼做塔防(1)

    最近学习到了项目期,分配了组员之后,我们经过一番推敲,决定做一个塔防类型游戏,首先我们先建立了游戏场景(第一关)。...

  • 小白贪狼做塔防(2)

    让我们继续探讨防御塔的建造,升级,卖出建造: 首先,/判断钱够不够/,够的话我们就将基座等级+1,并通过Canva...

  • 小白贪狼做塔防(6)

    首先我们创建GameData脚本用来处理玩家的数据 然后我们创建DataAdpter脚本,用来数据本地化,即在游戏...

  • C#——泛型类

    最近状态有点不对,所以就没有去更新笔记,塔防游戏也没继续开发,等调整好状态再继续塔防游戏。先做一些笔记找找感觉,估...

  • 九星断诀

    九星断诀: 1、《贪狼》: 贪狼入贪狼,富贵满朝堂。 贪狼入文曲官非主淫欲。 贪狼入破军官非横祸侵, 贪狼入禄存丁...

  • 2019-03-14 职场初探

    这些天的实习生活刷新了很多以前懵懂的认知从象牙塔的宠儿到职场小白观念转变得有点猝不及防但似乎又在情理之中 大概是3...

  • 塔防游戏——攻击方设计

    塔防游戏相信大家并不陌生,几个主要元素如下: 1、敌方士兵 2、我方防御塔 3、我方主城 emmmmmmm好像就没...

网友评论

    本文标题:小白贪狼做塔防(3)

    本文链接:https://www.haomeiwen.com/subject/eqcvuxtx.html