Unity3D-塔防游戏项目主要源码(游戏主控器脚本)
2017-09-08 19:21
399 查看
using UnityEngine; using System.Collections; using System.Collections.Generic;//引入泛型集合的命名空间 using UnityEngine.UI;//UI using UnityEngine.SceneManagement;//场景管理器 using UnityEngine.EventSystems;//引入事件系统 namespace TowerDefenceTemplate { [System.Serializable]//系统序列化 public class Wave//敌方炮车波数 { public Transform[] Waypoints;//路点数组 public Transform SpawnPoint;//产生敌方炮车的位置 public GameObject EnemyPrefab,//敌方炮车预制体 ArrowPoint;//进攻方向预制体 public Sprite EnemiesIcon;//敌方炮车的图标 public int Speed,//速率 Amount,//单波敌机总数 Interval,//时间间隔 Health,//血量 Damage,//伤害值 Award;//奖励金币 [HideInInspector] public int Spawned;//已经产生的敌机数 } public class GameManager : MonoBehaviour { private EventSystem _eventSystem;//实例化事件系统 [HideInInspector] public UI_Controller _UI_Controller;//实例化UI_Controller [HideInInspector] public MainMenu mainMenu; [HideInInspector] public int CurrentWaveIndex;//定义当前波数的索引 [HideInInspector] public List<GameObject> SpawnedEnemies,//声明敌方炮车游戏对象的集合 BuiltTowers;//声明已建炮塔游戏对象的集合 private GameObject[] TowerPoints;//定义所有炮塔的信息 private float Timer;//计时器 private int BaseHealth = 100;//总血量 private bool GameEnded;//定义游戏是否结束 private Tower TowerToEdit;//实例化塔的对象 [HideInInspector] public Dictionary<int, Bullet> BulletsPool;//定义炮弹池的键值对集合 [HideInInspector] public Dictionary<int, Rocket> RocketsPool;//定义导弹池的键值对集合 private GameObject RocketsPoolParent,//父导弹池 BulletsPoolParent,//父炮弹池 TempTower,//临时塔 TowerToBuild;//将要建造的塔 //UI [HideInInspector] public RectTransform BaseHealthBar;//矩形血条 [HideInInspector] public Text//文本 MoneyMessage, //金币信息 WaveNumber,//当前波数 WaveUpperNumber,//总波数 MoneyText,//钱币 EnemiesLeftText,//没被摧毁的敌方炮车数量 WaveTimer,//波次倒计时 NameText,//名字 DamageText,//伤害值 RangeText,//检测范围 LevelText,//等级 UpgradeButtonText,//升级按钮 SellButtonText;//卖掉按钮 [HideInInspector] public Image //图像 EnemiesIcon;//敌方炮车图标 [HideInInspector] public Button ToMenuButton,//回到菜单 RestartButton;//重新开始本关卡 [HideInInspector] public GameObject//定义游戏对象 RightPanel,//右侧小面板 PauseMenu,// UpgradeButton;//升级按钮 [Header("Camera boundaries")]//摄相机范围(组件中的小标题) public float X_Min; public float X_Max; public float Z_Min; public float Z_Max; public Wave[] Waves;//实例化波数 public int Money;//定义玩家的金币 [Header("Sounds")]//音效 public AudioSource BuildSound;//建塔音效 public AudioSource BaseDamageSound;//总血量减少时的音效 public AudioSource ErrorSound;//错误提示音效 public AudioSource ExplosionSound;//敌方炮车死亡时音效 public AudioSource LevelUpSound;//等级提升音效 public AudioSource LightGunShootSound;//光速炮射击音效 public AudioSource RicochetSound1;//炮弹弹跳音1 public AudioSource RicochetSound2;//炮弹弹跳音2 public AudioSource RicochetSound3;//炮弹弹跳音3 public AudioSource RocketLaunchSound;//导弹发射器射击音效 public AudioSource RocketExplosionSound;//导弹爆炸音效 public AudioSource FlameThrowerSound;//火焰喷射器射击音效 public AudioSource JeepSound;//吉普车行进音效 public AudioSource TankSound;//坦克行进音效 public AudioSource PlaneSound;//飞机行进音效 public AudioSource SellSound;//卖出炮塔音效 [Header("Prefabs")]//预制体 public GameObject RocketLauncherPrefab;//火箭发射器的预制体 public GameObject LightGunPrefab;//光速炮的预制体 public GameObject FlameThrowerPrefab;//火焰喷射器的预制体 public GameObject HealthBarPrefab;//总血量预制体 public GameObject BulletPrefab;//炮弹预制体 public GameObject RocketPrefab;//导弹预制体 private Camera main; void Start() { main = GameObject.Find("Main Camera").GetComponent<Camera>(); if (Waves.Length > 0)//如果波数大于0 { if (Waves[CurrentWaveIndex].ArrowPoint != null)//如果当前波次的进攻方向不为空 { Waves[CurrentWaveIndex].ArrowPoint.SetActive(true);//显示当前波次的进攻入口 } } else { Debug.LogError("Set up the GameManager waves!");//设定游戏管理器中的波数 enabled = false; } if (_UI_Controller == null)//如果UI控制器为空 { Debug.LogError("UI Canvas not found! GameManager is disabled.");//提示找不到画布 enabled = false; return; } TowerPoints = GameObject.FindGameObjectsWithTag("TowerPoint");//找出所有炮台的位点物体 _eventSystem = _UI_Controller._eventSystem;//为事件系统赋值 CreateBulletsPool(); CreateRocketsPool(); Timer = 5;//计时器设置为5 PauseMenu.SetActive(false);// MoneyText.text = Money.ToString() + "$";//改变当前的金币数 WaveUpperNumber.text = "Wave " + (CurrentWaveIndex + 1).ToString() + "/" + Waves.Length.ToString();//改变上面的波数显示 } void OnDrawGizmos()//画敌方炮车路线图,生命周期函数,只在编辑状态下被调用 { foreach (var wave in Waves)//遍历所有波次 { for (int i = 1; i < wave.Waypoints.Length; i++)//遍历所有路点 { Gizmos.DrawLine(wave.Waypoints[i].position, wave.Waypoints[i - 1].position);//用直线连接路点 } } } public void CreateBulletsPool()//创建炮弹池 { BulletsPool = new Dictionary<int, Bullet>();//实例化新对象 BulletsPoolParent = new GameObject("BulletsPool");//实例化父炮弹池并命名 for (int i = 0; i < 30 * TowerPoints.Length; i++)//遍历所有炮塔 { GameObject _newbullet = Instantiate(BulletPrefab);//克隆炮弹预制体 BulletsPool[i] = _newbullet.GetComponent<Bullet>();//获取克隆炮弹的Bullet脚本 BulletsPool[i].gameObject.SetActive(false);//让炮弹池所在对象失活 BulletsPool[i].transform.parent = BulletsPoolParent.transform;//把父炮弹池的位置信息赋值给炮弹池的父亲位置 } } public void CreateRocketsPool()//创建导弹池 { RocketsPool = new Dictionary<int, Rocket>(); RocketsPoolParent = new GameObject("RocketsPool"); for (int i = 0; i < 5 * TowerPoints.Length; i++) { GameObject _newRocket = Instantiate(RocketPrefab); RocketsPool[i] = _newRocket.GetComponent<Rocket>(); RocketsPool[i].gameObject.SetActive(false); RocketsPool[i].transform.parent = RocketsPoolParent.transform; } } public void SpendMoney(int moneyAmount)//花费金币 { Money -= moneyAmount;//当前钱币减去花费的金币数赋值给当前金币数 MoneyText.text = Money.ToString() + "$";//改变UGUI显示内容 } public void AddMoney(int moneyAmount)//增加金币 { Money += moneyAmount;//当前钱币加上奖励的金币数赋值给当前金币数 MoneyText.text = Money.ToString() + "$";//改变UGUI显示内容 } void Update() { if (GameEnded)//如果游戏结束 { return;//结束当前方法 } Timer = Mathf.MoveTowards(Timer, 0, Time.deltaTime);//倒计时 DoNavigation();//地图拖动 ControlMoneyMessageColor(false);//控制提示钱币信息的颜色 CountEnemiesLeft();//计数每波敌人存活的个数 CountTimeTillWaveStart();//下一波等待时间 CountEnemiesSpawnerTimer();//计数敌方炮车总数 PositioningTower();//给炮塔定位 CreatingTower();//创建塔 if (Input.GetKeyDown("mouse 0") && !_eventSystem.IsPointerOverGameObject() && TowerToEdit != null)//如果按下鼠标左键并且事件系统的对象的指针存在,并且实例化的塔对象不为空 { DeactivateTowerControl();//使塔控制器失效 } } void DoNavigation()//地图拖动 { if (_eventSystem.IsPointerOverGameObject()) //事件系统的对象的指针不存在 { return;//结束当前方法 } if (Input.GetKey("mouse 0") && TempTower == null)//如果按着鼠标左键并且临时塔为空 { Camera.main.transform.position += new Vector3(-Input.GetAxis("Mouse X"), 0, -Input.GetAxis("Mouse Y"));//移动主摄像机的位置 } Camera.main.transform.position = new Vector3(Mathf.Clamp(Camera.main.transform.position.x, X_Min, X_Max), Camera.main.transform.position.y, Mathf.Clamp(Camera.main.transform.position.z, Z_Min, Z_Max));//限制相机的移动范围 float autoScale = Input.GetAxis("Mouse ScrollWheel"); main.orthographicSize *= 1 - autoScale; main.orthographicSize = Mathf.Clamp(main.orthographicSize, 10, 55); } void CountEnemiesSpawnerTimer()//计数敌方炮车 { if (Timer == 0)//如果本波次敌人产生完 { WaveNumber.gameObject.SetActive(false);//当前波次设置失活 if (Waves[CurrentWaveIndex].ArrowPoint != null)//如果当前波次的方向箭头不为空 { Waves[CurrentWaveIndex].ArrowPoint.SetActive(false);//让它失活 } Timer = Waves[CurrentWaveIndex].Interval;//等待一段时间 EnemiesIcon.overrideSprite = Waves[CurrentWaveIndex].EnemiesIcon;//修改上面敌方炮车类型的图标为当前波次的敌方炮车图标 int _spawned = Waves[CurrentWaveIndex].Spawned;//本波次当前的敌机数量 int _amount = Waves[CurrentWaveIndex].Amount;//奔波次应产生的敌机总数 if (_spawned < _amount)//没产够 { SpawnEnemy();//生产敌方炮车 } else if (SpawnedEnemies.Count == 0)//如果产完了本波次的所有炮车,但都已被摧毁 { JeepSound.Stop();//停止音效 TankSound.Stop(); PlaneSound.Stop(); Timer = 5;//重新赋值为5 WaveNumber.gameObject.SetActive(true);//当前波次激活 if (CurrentWaveIndex < (Waves.Length - 1))//如果当前波次不是最后一波 { CurrentWaveIndex += 1;//已生产的波次索引+1 WaveUpperNumber.text = "Wave " + (CurrentWaveIndex + 1).ToString() + "/" + Waves.Length.ToString();//改变面板提示信息 Waves[CurrentWaveIndex].ArrowPoint.SetActive(true);//设置当前波次的行进箭头为激活状态 WaveNumber.text = "Wave " + (CurrentWaveIndex + 1).ToString();//屏幕中间提示第几波 } else { YouWon();//胜利 } } } } void CountTimeTillWaveStart()//开始下一波次前的等待时间 { if (SpawnedEnemies.Count == 0)//如果本波次的敌方炮车都已被摧毁 { WaveTimer.text = "0:0" + ((int)Timer).ToString();//重置等待时间 } } void CountEnemiesLeft()//计数存活的敌人 { int Killed, EnemiesLeft; Killed = Waves[CurrentWaveIndex].Spawned - SpawnedEnemies.Count;//已经被摧毁的敌方炮车数量 EnemiesLeft = Waves[CurrentWaveIndex].Amount - Killed;//没有被摧毁的炮车数量 EnemiesLeftText.text = EnemiesLeft.ToString();//显示在画板上 } void ControlMoneyMessageColor(bool ShowMessage)//控制钱币信息的颜色 { Color _color = MoneyMessage.color; _color.a = Mathf.MoveTowards(_color.a, 0, Time.deltaTime); if (ShowMessage) { _color.a = 1; } MoneyMessage.color = _color; } public void ThrowMoneyMessage()//抛出钱币信息 { ControlMoneyMessageColor(true);//改变钱币数颜色 ErrorSound.Play();//播放错误音效 } public void UpgradeTower()//防御塔升级 { if (TowerToEdit.UpgradeCost > Money)//如果当前金币不够升级的花销 { ThrowMoneyMessage();//提示不够 return;//结束当前方法 } TowerToEdit.Upgrade();//调用实例对象自身的升级方法 SpendMoney(TowerToEdit.UpgradeCost/2);//花费金币 if (TowerToEdit.Level == TowerToEdit.Damage.Length - 1)//如果塔对象的等级等于最后的伤害值 { UpgradeButton.SetActive(false);//设置升级按钮失活 } else { UpgradeButton.SetActive(true);//一直可以升级 } LevelUpSound.Play();//升级音效播放 UpdateTowerInfo();//更新防御塔的信息 } public void SellTower()//卖塔 { AddMoney(TowerToEdit.UpgradeCost / 2);//加钱 Destroy(TowerToEdit.gameObject);//摧毁这个塔 SellSound.Play();//卖出音效播放 DeactivateTowerControl();//这个塔的控制器失效 } void UpdateTowerInfo()//更新塔的信息 { UpgradeButtonText.text = "Upgrade " + TowerToEdit.UpgradeCost.ToString() + "$";//UGUI面板升级花费 SellButtonText.text = "Sell " + (TowerToEdit.Cost / 2).ToString() + "$";//卖塔价钱 NameText.text = TowerToEdit.TowerName;//塔的名字 LevelText.text = "Level " + (TowerToEdit.Level + 1).ToString();//塔的等级 DamageText.text = "Damage " + TowerToEdit.Damage[TowerToEdit.Level].ToString();//伤害值 RangeText.text = "Range " + TowerToEdit.Range[TowerToEdit.Level].ToString();//检测范围 } void YouLose()//游戏失败 { ToMenuButton.gameObject.SetActive(true);//返回开始菜单按钮被激活 RestartButton.gameObject.SetActive(true);//重新开始本关卡按钮被激活 GameEnded = true;//游戏结束 if (_UI_Controller != null)//如果UI控制器的对象不为空 { _UI_Controller.GameEnd();//执行结束方法 } WaveNumber.gameObject.SetActive(true);//当前波次对象被激活 WaveNumber.text = "You lose!";//被激活的对象内容显示你失败了 } void YouWon()//游戏胜利 { ToMenuButton.gameObject.SetActive(true);//返回开始菜单按钮被激活 RestartButton.gameObject.SetActive(true);//重新开始本关卡按钮被激活 GameEnded = true;//游戏结束 if (_UI_Controller != null)//如果UI控制器的对象不为空 { _UI_Controller.GameEnd();//执行结束方法 } WaveNumber.gameObject.SetActive(true);//当前波次对象被激活 WaveTimer.gameObject.SetActive(false);//波次倒计时器设置失活 WaveNumber.text = "You won!";//被激活的对象内容显示你胜利了 } public void ActivateTowerControl(Tower tower)//激活炮塔控制器 { RightPanel.SetActive(true);//右侧菜单激活 TowerToEdit = tower;//控制塔的实例化对象 if (TowerToEdit.Level == TowerToEdit.Damage.Length - 1) { UpgradeButton.SetActive(false); } else { UpgradeButton.SetActive(true); } UpdateTowerInfo(); } public void DeactivateTowerControl()//失活炮塔控制器 { RightPanel.SetActive(false);//右侧菜单失活 if (TowerToEdit != null)//如果防御塔对象不为空 { TowerToEdit.DetectCircle.gameObject.SetActive(false);//设置防御塔的侦测圆失活 } TowerToEdit = null;//让对象为空 } public void DamageBase()//玩家血量的伤害 { BaseHealth -= Waves[CurrentWaveIndex].Damage;//血量减少 BaseDamageSound.Play();//血量受到伤害的音效 BaseHealthBar.localScale = new Vector3(BaseHealth / 100f, 1, 1);//对血条预制体实行x方向的缩放 if (BaseHealth <= 0)//如果血量非正 { YouLose();//失败方法 BaseHealth = 100;//重新赋值为100 } } public void BackToMenu()//返回主菜单 { SceneManager.LoadScene("Menu");//加载场景Menu } public void RestartLevel()//重新开始本关卡 { SceneManager.LoadScene(SceneManager.GetActiveScene().name);//按当前场景名字加载当前场景 } public void BuildingModeOn(string type)//建造模型 { if (type == "lightgun")//如果类型为ligthgun,并且按钮可按 { TowerToBuild = LightGunPrefab;//将要建造的塔的游戏对象赋值为光速炮的预制体 } if (type == "rocketlauncher") { TowerToBuild = RocketLauncherPrefab; } if (type == "flamethrower") { TowerToBuild = FlameThrowerPrefab; } TempTower = Instantiate(TowerToBuild);//克隆即将要建的塔赋值给临时塔 } void PositioningTower()//确定新建塔的位置 { if (TempTower == null)//如果临时塔为空 { return; } RaycastHit hit;//射线碰撞体 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//鼠标位置发射一条射线 if (Physics.Raycast(ray, out hit))//射线检测 { TempTower.transform.position = hit.point;//临时炮塔放在鼠标位置 } } void CreatingTower()//创建塔 { if (TempTower == null || TowerPoints.Length == 0)//如果临时塔为空或者没有地方放置塔 { return; } GameObject ClosestTowerPoint = TowerPoints[0];//设置第一个塔点为最靠近的鼠标位置的塔点 Vector3 ClosestTowerPointPosition = TowerPoints[0].transform.position;//它的位置为第一个塔点的位置 foreach (var towerpoint in TowerPoints)//遍历所有的塔点 { if (Vector3.Distance(TempTower.transform.position, towerpoint.transform.position) < Vector3.Distance(ClosestTowerPointPosition, TempTower.transform.position))//当临时塔的位置与塔点位置的距离小于最近塔与临时塔的距离 { ClosestTowerPoint = towerpoint;//把这个塔点赋值给最近的塔点 ClosestTowerPointPosition = towerpoint.transform.position;//赋值相应的位置信息 } } if (Input.GetKeyUp("mouse 0"))//当抬起鼠标左键时 { if (Money < TempTower.GetComponent<Tower>().Cost)//如果当前的金币数小于建塔要花费的金币 { ThrowMoneyMessage();//提示钱不够 Destroy(TempTower);//销毁临时塔 return;//结束当前方法 } if (Vector3.Distance(TempTower.transform.position, ClosestTowerPointPosition) > 5 || ClosestTowerPoint.transform.childCount > 0)//如果临时塔和最塔点的距离大于5或者最近塔点没有子塔点 { Destroy(TempTower);//销毁临时塔 ErrorSound.Play();//错误音效 return;//结束当前方法 } SpendMoney(TempTower.GetComponent<Tower>().Cost);//建塔花费金币 BuiltTowers.Add(TempTower);//添加到已建造的集合 float _verticalOffset = ClosestTowerPoint.AddComponent<BoxCollider>().bounds.size.y;//获取最近塔点的盒子碰撞器的长度,作为炮台高 Destroy(ClosestTowerPoint.GetComponent<BoxCollider>());//销毁盒子碰撞器 SphereCollider _tempCollider = TempTower.AddComponent<SphereCollider>();//给临时塔添加球形碰撞体 _tempCollider.radius = 5;//半径为5 TempTower.transform.position = ClosestTowerPointPosition + new Vector3(0, _verticalOffset, 0);//把临时塔放在最近塔点位置,并以炮台的高度作为底面高 TempTower.transform.parent = ClosestTowerPoint.transform;//把最近塔点的位置赋值给临时塔的父物体位置 TempTower = null;//临时塔设置为空 BuildSound.Play();//建塔音效播放 } } public void Pause()//暂停 { Time.timeScale = 0; } public void UnPause()//播放 { Time.timeScale = 1; } public void Fast()//加快 { Time.timeScale = 3; } void SpawnEnemy()//生产敌方炮车 { Waves[CurrentWaveIndex].Spawned += 1;//已造出的炮车数量增加1 GameObject _newEnemy = Instantiate(Waves[CurrentWaveIndex].EnemyPrefab, Waves[CurrentWaveIndex].SpawnPoint.position, Waves[CurrentWaveIndex].SpawnPoint.rotation) as GameObject;//克隆新的敌方炮车 GameObject _healthBar = _newEnemy.GetComponent<Enemy>().HealthBar = Instantiate(HealthBarPrefab) as GameObject;//克隆炮车的血条 _healthBar.transform.parent = _UI_Controller.transform;//定义血条的父物体为_UI_Controller SpawnedEnemies.Add(_newEnemy);//把新炮车添加到敌方炮车集合中 } } }
相关文章推荐
- Unity3D-塔防游戏项目主要源码(防御塔炮弹脚本)
- Unity3D-塔防游戏项目主要源码(防御塔导弹脚本)
- Unity3D-塔防游戏项目主要源码(游戏UI界面控制器脚本)
- Unity3D-塔防游戏项目主要源码(游戏主菜单脚本)
- Unity3D-塔防游戏项目主要源码(防御塔脚本)
- Unity3D-塔防游戏项目主要源码(敌方炮车脚本)
- [Unity3D]Unity3D游戏开发之塔防游戏项目讲解(上)
- [Unity3D]手机3D游戏开发:简单的移动和缩放鼠标手势脚本源码
- [Unity3D]手机3D游戏开发:如何实现最高分的存储与显示(九)----使用PreviewLabs插件提速与完整的项目源码
- Unity3D 篮球游戏 上线项目源码
- [Unity3D]手机3D游戏开发:关于自定义Joystick的相关设置和脚本源码
- Unity3D-深入剖析NGUI的游戏UI架构 --主要讲了UIWiget,UIDrawCall,UINode,UIPanel
- 【Unity教程】Unity3D之游戏架构脚本该如何来写
- Unity3D 大型游戏 最后一站 源码 部分重点ResourceManager(2)
- 激情台球游戏源码项目
- 双人对战的球类游戏ios源码项目
- 【UNITY3D 游戏开发之三】NGUI && HUDText 的练习源码及资源
- java实现潜艇大战游戏之Java swing图形界面开发游戏项目潜艇大战源码及实现方式详解
- 100层跳板游戏源码项目
- unity3d阶段性学习脚本代码(2个是摄像机跟随(2D游戏中的),1个是角色跳跃移动脚本)