您的位置:首页 > 移动开发 > Unity3D

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);//把新炮车添加到敌方炮车集合中
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息