Unity3D-塔防遊戲專案主要原始碼(防禦塔指令碼)

一楓一葉舟發表於2017-09-08
using UnityEngine;
using System.Collections;

namespace TowerDefenceTemplate
{
    public class Tower : MonoBehaviour
    {
        public enum TowerType//防禦塔型別
        {
            LightGun,//光速炮
            RocketLauncher,//火箭發射器
            FlameThrower//火焰噴射器
        };

        public TowerType towerType;//例項化防禦塔型別

        public int
            Cost,//建一個塔所花費的金幣數
            UpgradeCost;//升級一個塔所花費的金幣數

        [HideInInspector]
        public int Level;//炮塔等級

        public int[]
            Range,//炮塔的攻擊範圍
            Damage;//傷害值

        public string TowerName;//炮塔的名字

        public GameObject
            Body,//炮塔的身體
            Head;//炮頭

        public EllipsoidParticleEmitter
            Fire1,//2種粒子特效
            Fire2,
            Flame;//噴火特效

        private float Timer;//定義計時器

        private GameManager gameManager;//例項化GameManager物件

        private GameObject CurrentTarget;//定義當前的攻擊目標

        public Transform
            GunPoint1,//2個射擊點
            GunPoint2,
            DetectCircle;//偵查圈

        void Start()
        {
            gameManager = FindObjectOfType<GameManager>();//獲取指令碼
            DetectCircle.localScale = new Vector3(Range[Level], DetectCircle.localScale.y, Range[Level]);//炮塔等級不同,檢測範圍不同
            if (gameManager == null)
            {
                Debug.LogError("GameManager not found!");
                enabled = false;
            }
        }

        void OnMouseUp()
        {
            DetectCircle.gameObject.SetActive(true);//啟用檢測器所在的遊戲物件
            gameManager.ActivateTowerControl(this);
        }

        void Update()
        {
            if (transform.parent == null)//如果沒有父物體
            {
                return;//結束當前方法
            }
            float _detectRange = DetectCircle.localScale.x / 2;//偵測範圍在X方向縮小一半
            Timer = Mathf.MoveTowards(Timer, 0, Time.deltaTime);//從當前時刻按秒數趨向0
            if (CurrentTarget == null)//如果當前目標為空
            {
                SearchTarget();//搜尋目標
            }
            if (CurrentTarget != null)//如果當前目標非空
            {
                Vector3 ProjectionOnGround = new Vector3(CurrentTarget.transform.position.x, transform.position.y, CurrentTarget.transform.position.z);//定義目標點位置
                if (Vector3.Distance(transform.position, ProjectionOnGround) > _detectRange || CurrentTarget.tag == "Dead")//如果目標已出偵查範圍或者目標已陣亡
                {
                    CurrentTarget = null;//把目標設為空
                    return;//結束當前方法
                }
                Vector3 ThisPosition = transform.position;//記錄當前位置資訊
                Quaternion TargetBodyRotation = Quaternion.LookRotation(new Vector3(CurrentTarget.transform.position.x, ThisPosition.y, CurrentTarget.transform.position.z) - transform.position, transform.up);//定義四元數做炮座旋轉
                Quaternion TargetHeadRotation = Quaternion.LookRotation(CurrentTarget.transform.position - Head.transform.position, transform.up);//定義四元數做炮頭旋轉
                Body.transform.rotation = Quaternion.RotateTowards(Body.transform.rotation, TargetBodyRotation, Time.deltaTime * 100);//以自身y軸為軸,讓身體做旋轉
                Head.transform.rotation = Quaternion.RotateTowards(Head.transform.rotation, TargetHeadRotation, Time.deltaTime * 50);//讓炮塔頭看著目標
                if (Quaternion.Angle(Head.transform.rotation, TargetHeadRotation) < 2)//如果炮頭的旋轉度數小於2時
                {
                    if (towerType == TowerType.LightGun)//如果塔的型別是光速炮
                    {
                        AttackingLightGun();//執行光速炮射擊
                    }
                    if (towerType == TowerType.RocketLauncher)//如果塔的型別是火箭發射器
                    {
                        AttackingRocketLauncher();//執行火箭發射器攻擊
                    }
                    if (towerType == TowerType.FlameThrower)//如果塔的型別是火焰噴射器
                    {
                        AttackingFlameThrower();//執行噴射火焰
                    }
                }
            }
            else
            {
                if (towerType == TowerType.FlameThrower)//當炮塔型別為火焰噴射器時
                {
                    StopFlaming();//停止噴射火焰
                }
            }
        }

        public void Upgrade()//炮塔升級
        {
            Level++;//等級提升
            DetectCircle.localScale = new Vector3(Range[Level], DetectCircle.localScale.y, Range[Level]);//偵測半徑擴大一倍
            UpgradeCost *= 2;
        }

        void SearchTarget()//搜尋目標
        {
            foreach (var item in gameManager.SpawnedEnemies)
            {
                Vector3 ProjectionOnGround = new Vector3(item.transform.position.x, transform.position.y, item.transform.position.z);//定義所有敵方戰車的位置
                if (item.tag == "Plane" && towerType != TowerType.RocketLauncher)//如果敵方戰車是飛機並且炮塔型別不是火箭發射器時
                {
                    continue;//查詢下一個
                }
                if (Vector3.Distance(transform.position, ProjectionOnGround) < DetectCircle.localScale.x / 2)//如果敵方戰車進入到炮塔的檢測範圍(檢測圓的半徑)
                {
                    CurrentTarget = item;//把此敵人設為攻擊目標
                }
            }
        }

        void StopFlaming()//停止噴射火焰
        {
            Flame.emit = false;//噴射火焰粒子系統false
            gameManager.FlameThrowerSound.Stop();//停止噴火聲效
        }

        void AttackingLightGun()//光速炮攻擊
        {
            if (Timer == 0)//當計時器為 0時
            {
                Timer = 0.3f;//重新定值為0.3s
                ShootLightGun(GunPoint1);//兩個炮筒同時射擊
                ShootLightGun(GunPoint2);
                Fire1.Emit();//呼叫粒子系統作為子彈從炮口打出的特效
                Fire2.Emit();
                gameManager.LightGunShootSound.Play();//播放光速炮射擊音效 
            }
        }

        void ShootLightGun(Transform gunpoint)//光速炮射擊
        {
            Bullet _tempbul;//炮彈
            for (int i = 0; i < gameManager.BulletsPool.Count; i++)
            {
                if (!gameManager.BulletsPool[i].gameObject.activeSelf)
                {
                    _tempbul = gameManager.BulletsPool[i];//給炮彈例項化物件
                    _tempbul.target = CurrentTarget;//定義炮彈的目標為當前炮塔檢測到的目標
                    _tempbul.Damage = Damage[Level];//炮彈的傷害值為當前等級的傷害值
                    _tempbul.gameObject.SetActive(true);//啟用炮彈
                    _tempbul.transform.position = gunpoint.position;//炮彈位置為射擊點gunpoint
                    _tempbul.transform.rotation = gunpoint.rotation;//炮彈的旋轉度等於射擊點的旋轉度
                    break;//結束當前迴圈
                }
            }
            int random = Random.Range(0, 20);//生成0-19的隨機整數
            if (random == 1)//1/20的概率播放
            {
                gameManager.RicochetSound1.Play();//射擊子彈的聲效
            }
            if (random == 10)
            {
                gameManager.RicochetSound2.Play();
            }
            if (random == 20)
            {
                gameManager.RicochetSound3.Play();
            }
        }

        void AttackingRocketLauncher()
        {
            if (Timer == 0)//當計時器減到0時
            {
                Timer = 2;//讓計時器值為2
                StartCoroutine(ShootRocketLauncher());//開始協同程式
            }
        }

        IEnumerator ShootRocketLauncher()//列舉器  火箭發射器射擊狀態
        {
            Rocket _temproc;//導彈
            for (int i = 0; i < gameManager.RocketsPool.Count; i++)
            {
                if (!gameManager.RocketsPool[i].gameObject.activeSelf)//第一個炮筒的發射過程
                {
                    _temproc = gameManager.RocketsPool[i];//給導彈例項化物件
                    _temproc.Damage = Damage[Level];//導彈的傷害值為當前的等級傷害
                    _temproc.Target = CurrentTarget;//導彈的目標為當前檢測到的目標
                    _temproc.gameObject.SetActive(true);//啟用導彈
                    _temproc.transform.position = GunPoint1.position;//導彈的位置在射擊點GunPoint1
                    _temproc.transform.rotation = GunPoint1.rotation;//導彈隨射擊點旋轉
                    gameManager.RocketLaunchSound.Play();//發射導彈的音效播放
                    Fire1.Emit();//導彈噴火粒子系統開啟
                    break;//結束當前迴圈
                }
            }
            yield return new WaitForSeconds(0.3f);//等待0.3s
            for (int i = 0; i < gameManager.RocketsPool.Count; i++)
            {
                if (!gameManager.RocketsPool[i].gameObject.activeSelf)//第二個炮筒的發射過程
                {
                    _temproc = gameManager.RocketsPool[i];
                    _temproc.Damage = Damage[Level];
                    _temproc.Target = CurrentTarget;
                    _temproc.gameObject.SetActive(true);
                    _temproc.transform.position = GunPoint2.position;
                    _temproc.transform.rotation = GunPoint2.rotation;
                    gameManager.RocketLaunchSound.Play();
                    Fire2.Emit();
                    break;
                }
            }
        }

        void AttackingFlameThrower()//噴火器攻擊
        {
            Flame.emit = true;//噴火粒子系統呼叫
            CurrentTarget.SendMessage("GetDamage", Damage[Level] * Time.deltaTime);//得到持續性傷害
            if (!gameManager.FlameThrowerSound.isPlaying)//如果現在沒有播放噴火聲效
            {
                gameManager.FlameThrowerSound.Play();//開啟聲效
            }
        }
    }
}

相關文章