首页 > 代码库 > Demo_塔防(自动生成怪物,导航,炮塔攻击,怪物掉血死忙)

Demo_塔防(自动生成怪物,导航,炮塔攻击,怪物掉血死忙)

技术分享

using UnityEngine;
using System.Collections;

public struct WaveMsg
{
    //该波次生成的怪物
    public GameObject monster;
    //时间间隔
    public float waveInterval;
    //生成个数
    public float count;
    //生成间隔
    public float interval;
    //怪物血量
    public float hp;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="monster">Monster.</param>
    /// <param name="waveInterval">Wave interval.</param>
    /// <param name="count">Count.</param>
    /// <param name="interval">Interval.</param>
    public WaveMsg(GameObject monster,float waveInterval,
            float count,float interval,float hp)
    {
        this.monster = monster;
        this.waveInterval = waveInterval;
        this.count = count;
        this.interval = interval;
        this.hp = hp;
    }
}

public class MonsterInit : MonoBehaviour {

    //怪物预设体
    public GameObject[] monsters;
    //波次信息
    public WaveMsg[] waveMsg;
    //每波怪之间的时间计时器
    private float waveTimer;
    //每个怪之前的时间计时器
    private float monsterTimer;
    //波次计数器
    private int count;
    //怪物个数计数器
    private int monsterCount;
    //游戏开关
    private bool gameBegin = true;

    void Awake()
    {
        waveMsg = new WaveMsg[]{
            new WaveMsg(monsters[0],0,3,2,10),
            new WaveMsg(monsters[1],2.5f,5,1.5f,15),
            new WaveMsg(monsters[2],2,10,1f,20),
            new WaveMsg(monsters[1],2,10,0.5f,25),
            new WaveMsg(monsters[0],2,15,0.5f,30)
        };
    }

    void Update()
    {
        if (gameBegin) {
            //波次计时器计时
            waveTimer += Time.deltaTime;
            if (waveTimer >= waveMsg [count].waveInterval) {
                //如果当前生成怪的个数不够,继续生成
                if (monsterCount < waveMsg [count].count) {
                    //计时器计时
                    monsterTimer += Time.deltaTime;
                    //计时结束
                    if (monsterTimer > waveMsg [count].interval) {
                        //生成怪物
                        GameObject currentMaster = Instantiate (
                            waveMsg [count].monster,
                            transform.position, 
                            Quaternion.identity) as GameObject;
                        //给新生成的怪物设置血量值
                        currentMaster.GetComponent<Monster> ().hp = 
                            waveMsg [count].hp;
                        //怪物个数++
                        monsterCount++;
                        //计时器清零
                        monsterTimer = 0;
                    }
                } else {
                    //波次加一
                    count++;
                    if (count < waveMsg.Length) {
                        //怪物个数清零
                        monsterCount = 0;
                        //波次计时器清零
                        waveTimer = 0;
                    } else {
                        //表示怪兽生成结束
                        gameBegin = false;
                    }
                }
            }
        }
    }
}

技术分享

using UnityEngine;
using System.Collections;

public class GameOver : MonoBehaviour {

    //血量
    public int hp = 10;

    //触发
    void OnTriggerEnter(Collider other)
    {
        //如果是怪物
        if (other.tag == "Monster") {
            //减血操作
            if (--hp <= 0) {
                Debug.Log ("GameOver");
            }
            //销毁怪物
            Destroy (other.gameObject);
        }
    }
}

技术分享

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

public class GaussAttack : MonoBehaviour {

    //攻击队列
    Queue<Transform> monsters;
    //当前攻击目标
    public Transform currentTarget;
    //炮筒旋转速度
    public float turnSpeed = 10;
    //发射特效
    private GameObject muzzle;
    //炮塔伤害值
    public float damage = 30;

    void Awake()
    {
        monsters = new Queue<Transform> ();
        muzzle = transform.Find ("Base/Turret/Muzzle_1").gameObject;
    }

    void Update()
    {
        if (currentTarget) {
            //转向
            LookAtTargetSmooth();
            //给敌人减血
            currentTarget.GetComponent<Monster>().hp-=Time.deltaTime * damage;
            //如果当前目标已经死亡
            if (!currentTarget.GetComponent<Monster> ().monsterAlive) {
                //切换下一个目标
                TargetSwitch ();
            }
        }
    }

    /// <summary>
    /// 平滑旋转看向敌人
    /// </summary>
    void LookAtTargetSmooth()
    {
        //方向向量
        Vector3 dir = currentTarget.position - transform.position;
        //目标旋转
        Quaternion qua = Quaternion.LookRotation (dir);
        //先找到炮筒
        Transform gun = transform.GetChild (0).GetChild (0);
        //炮筒转向目标四元数
        gun.rotation = Quaternion.Lerp (gun.rotation, qua,
            Time.deltaTime * turnSpeed);
    }

    /// <summary>
    /// 进入攻击范围
    /// </summary>
    /// <param name="other">Other.</param>
    void OnTriggerEnter(Collider other)
    {
        //如果是怪物
        if (other.tag == "Monster") {
            //进队列
            monsters.Enqueue (other.transform);
            // 如果没有攻击目标
            if (currentTarget == null) {
                TargetSwitch ();
            }
        }
    }

    void OnTriggerExit(Collider other)
    {
        //如果是怪物,且在队列内
        if (other.tag == "Monster" && other.transform == currentTarget) {
            //切换下一个目标
            TargetSwitch ();
        }
    }

    /// <summary>
    /// 切换目标
    /// </summary>
    void TargetSwitch()
    {
        //如果队列中有数据
        if (monsters.Count > 0) {
            //队列中出来的怪物即为下一个攻击目标
            currentTarget = monsters.Dequeue ();
            //有怪,开枪
            muzzle.SetActive (true);
        } else {
            //如果队列中没有数据,此时目标为空
            currentTarget = null;
            //没怪,停止开枪
            muzzle.SetActive (false);
        }
    }
}

技术分享

using UnityEngine;
using System.Collections;

public class CameraMove : MonoBehaviour {

    private float hor,ver;
    public float moveSpeed = 3;

    void Update()
    {
        hor = Input.GetAxis ("Horizontal");
        ver = Input.GetAxis ("Vertical");

        transform.position += new Vector3 (hor,0,ver)
            * Time.deltaTime * moveSpeed;
        //24 0 2
        //40 0 35

        transform.position = new Vector3 (
            Mathf.Clamp(transform.position.x,24f,40f),
            transform.position.y,
            Mathf.Clamp(transform.position.z,2f,35f)
        );

    }

}
using UnityEngine;
using System.Collections;

public class TowerInit : MonoBehaviour {

    //射线碰撞检测器
    RaycastHit hit;
    //炮塔预设体
    public GameObject towerPrefab;

    void Update()
    {
        //获取屏幕射线
        Ray r = Camera.main.ScreenPointToRay (
            Input.mousePosition);
        //射线碰撞到了碰撞体
        if (Physics.Raycast (r, out hit)) {
            //如果该物体名字中包含‘Base’字符串,且基座没有子物体
            if (hit.collider.name.Contains ("Base") &&
                hit.transform.childCount == 0) {
                if (Input.GetMouseButtonDown (0)) {
                    ///TODO:生成炮塔
                    GameObject currentTower = Instantiate (
                        towerPrefab,
                        hit.transform.position + Vector3.up * 2.7f,
                        Quaternion.identity) as GameObject;
                    //设置炮塔为基座的子物体
                    currentTower.transform.SetParent (hit.transform);
                }
            }
        }
    }

}

炮塔需要触发事件设置好范围来检测怪物,进入范围触发事件攻击。

地图设置导航。

怪物添加刚体,设置动力学。避免出现碰撞弹奏,或者穿透现象。

Demo_塔防(自动生成怪物,导航,炮塔攻击,怪物掉血死忙)