```csharp
// 自定义每波敌人的参数
2 [System.Serializable] // 序列化
3 public class Wave
4 {
5 public GameObject enemyPrefab; // 敌人模型
6 public int count; // 敌人数量
7 public float rate; // 敌人生成间隔
8 }
1 public class EnemySpawner : MonoBehaviour {
2 public Wave[] waves; // 定义每波敌人参数
3 public Transform start; // 敌人出生点
4 public int waveRate = 3; // 每波敌人生成间隔
5 public static int countEnemyAlive = 0; // 生存敌人个数
6
7 // Use this for initialization
8 void Start () {
9 StartCoroutine(SpawnEnemy()); // 启动线程
10 }
11
12 IEnumerator SpawnEnemy()
13 {
14 foreach(Wave wave in waves) // 遍历每一波敌人
15 {
16 for (int i = 0; i < wave.count; ++i) // 生成每个敌人
17 {
18 // 生成敌人
19 GameObject.Instantiate(wave.enemyPrefab, start.position, Quaternion.identity);
20 countEnemyAlive++; // 生存敌人个数+1
21 if (i != wave.count - 1) // 敌人生成间隔
22 yield return new WaitForSeconds(wave.rate);
23 }
24 while (countEnemyAlive > 0) // 上一波敌人全部死亡后,才能生成下一波敌人
25 {
26 yield return 0;
27 }
28 yield return new WaitForSeconds(waveRate); // 等待生成下一波敌人
29 }
30 }
31 }
```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public interface IBuilder<T> {

//获取到游戏物体身上的脚本对象,从而去赋值
T GetProductClass(GameObject gameObject);

//使用工厂去获取具体的游戏对象
GameObject GetProduct();

//获取数据信息
void GetData(T productClassGo);

//获取特有资源与信息
void GetOtherResource(T productClassGo);
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MonsterBuilder : IBuilder<Monster>
{
public int m_monsterID;
private GameObject monsterGo;

public void GetData(Monster productClassGo)
{
productClassGo.monsterID = m_monsterID;
productClassGo.HP = m_monsterID * 100;
productClassGo.currentHP = productClassGo.HP;
productClassGo.initMoveSpeed = m_monsterID;
productClassGo.moveSpeed = m_monsterID;
productClassGo.prize = m_monsterID * 50;
}

public void GetOtherResource(Monster productClassGo)
{
productClassGo.GetMonsterProperty();
}

public GameObject GetProduct()
{
GameObject itemGo = GameController.Instance.GetGameObjectResource("MonsterPrefab");
Monster monster = GetProductClass(itemGo);
GetData(monster);
GetOtherResource(monster);
return itemGo;
}

public Monster GetProductClass(GameObject gameObject)
{
return gameObject.GetComponent<Monster>();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 游戏控制管理,负责控制游戏的整个逻辑
/// </summary>
public class GameController : MonoBehaviour {

private static GameController _instance;
public static GameController Instance
{
get
{
return _instance;
}
}

//引用
public Level level;
private GameManager mGameManager;
public int[] mMonsterIDList;//当前波次的产怪列表
public Stage currentStage;
public MapMaker mapMaker;
public Transform targetTrans;//集火目标
public GameObject targetSignal;//集火信号
public GridPoint selectGrid;//上一个选择的格子

//游戏资源
public RuntimeAnimatorController[] controllers;//怪物的动画播放控制器

//游戏UI的面板
public NormalModelPanel normalModelpanel;

//用于计数的成员变量
public int killMonsterNum;//当前波次杀怪数
public int clearItemNum;//道具销毁数量
public int killMonsterTotalNum;//杀怪总数
public int mMonsterIDIndex;//用于统计当前怪物列表产生怪物的索引

//属性值
public int carrotHp = 10;
public int coin;
public int gameSpeed;//当前游戏进行速度
public bool isPause;
public bool creatingMonster;//是否继续产怪
public bool gameOver;//游戏是否结束

//建造者
public MonsterBuilder monsterBuilder;
public TowerBuilder towerBuilder;

//建塔有关的成员变量
public Dictionary<int, int> towerPriceDict;//建塔价格表
public GameObject towerListGo;//建塔按钮列表
public GameObject handleTowerCanvasGo;//处理塔升级与买卖的画布



private void Awake()
{
#if Game
_instance = this;
mGameManager = GameManager.Instance;
//测试代码
//currentStage = new Stage(10,5,new int[] { 1,2,3,4,5},false,0,1,1,true,false);
currentStage = mGameManager.currentStage;
normalModelpanel = mGameManager.uiManager.mUIFacade.currentScenePanelDict[StringManager.NormalModelPanel] as NormalModelPanel;
normalModelpanel.EnterPanel();
mapMaker = GetComponent<MapMaker>();
mapMaker.InitMapMaker();
mapMaker.LoadMap(currentStage.mBigLevelID,currentStage.mLevelID);
//成员变量赋值
gameSpeed = 1;
coin = 1000;

monsterBuilder = new MonsterBuilder();
towerBuilder = new TowerBuilder();
//建塔列表的处理
for (int i = 0; i < currentStage.mTowerIDList.Length; i++)
{
GameObject itemGo = mGameManager.GetGameObjectResource(FactoryType.UIFactory,"Btn_TowerBuild");
itemGo.transform.GetComponent<ButtonTower>().towerID = currentStage.mTowerIDList[i];
itemGo.transform.SetParent(towerListGo.transform);
itemGo.transform.localPosition = Vector3.zero;
itemGo.transform.localScale = Vector3.one;
}
//建塔价格表
towerPriceDict = new Dictionary<int, int>
{
{ 1,100},
{ 2,120},
{ 3,140},
{ 4,160},
{ 5,160}
};

controllers = new RuntimeAnimatorController[12];
for (int i = 0; i < controllers.Length; i++)
{
controllers[i] = GetRuntimeAnimatorController("Monster/"+mapMaker.bigLevelID.ToString()+"/"+(i+1).ToString());
}
level = new Level(mapMaker.roundInfoList.Count, mapMaker.roundInfoList);
normalModelpanel.topPage.UpdateCoinText();
normalModelpanel.topPage.UpdateRoundText();
//level.HandleRound();
isPause = true;
#endif
}

private void Update()
{
#if Game
if (!isPause)
{
//产怪逻辑
if (killMonsterNum>=mMonsterIDList.Length)
{
//添加当前回合数的索引
if (level.currentRound==level.totalRound)
{
return;
}
AddRoundNum();
}
else
{
if (!creatingMonster)
{
CreateMonster();
}
}
}
else
{
//暂停
StopCreateMonster();
creatingMonster = false;
}
#endif
}

/// <summary>
/// 与集火目标有关的方法
/// </summary>
public void ShowSignal()
{
PlayEffectMusic("NormalMordel/Tower/ShootSelect");
targetSignal.transform.position = targetTrans.position + new Vector3(0,mapMaker.gridHeight/2,0);
targetSignal.transform.SetParent(targetTrans);
targetSignal.SetActive(true);
}

public void HideSignal()
{
targetSignal.gameObject.SetActive(false);
targetTrans = null;
}

/// <summary>
/// 与玩家信息有关的方法
/// </summary>

//改变玩家金币
public void ChangeCoin(int coinNum)
{
coin += coinNum;
//更新游戏UI显示
normalModelpanel.UpdatePanel();
}

//萝卜血量减少
public void DecreaseHP()
{
PlayEffectMusic("NormalMordel/Carrot/Crash");
carrotHp--;
//更新萝卜UI显示
mapMaker.carrot.UpdateCarrotUI();
}

//判断当前道具是否全部清除
public bool IfAllClear()
{
for (int x = 0; x < MapMaker.xColumn; x++)
{
for (int y = 0; y < MapMaker.yRow; y++)
{
if (mapMaker.gridPoints[x,y].gridState.hasItem)
{
return false;
}
}
}
return true;
}

//获取萝卜状态
public int GetCarrotState()
{
int carrotState = 0;
if (carrotHp>=4)
{
carrotState = 1;
}
else if (carrotHp>=2)
{
carrotState = 2;
}
else
{
carrotState = 3;
}
return carrotState;
}

/// <summary>
/// 产生怪物的有关方法
/// </summary>
//产怪方法
public void CreateMonster()
{
creatingMonster = true;
InvokeRepeating("InstantiateMonster",(float)1/gameSpeed, (float)1 / gameSpeed);
}

//具体产怪方法
private void InstantiateMonster()
{
PlayEffectMusic("NormalMordel/Monster/Create");
if (mMonsterIDIndex >= mMonsterIDList.Length)
{
StopCreateMonster();
return;
}
//产生特效
GameObject effectGo = GetGameObjectResource("CreateEffect");
effectGo.transform.SetParent(transform);
effectGo.transform.position = mapMaker.monsterPathPos[0];
//产生怪物
if (mMonsterIDIndex<mMonsterIDList.Length)
{
monsterBuilder.m_monsterID = level.roundList[level.currentRound].roundInfo.mMonsterIDList[mMonsterIDIndex];
}

GameObject monsterGo = monsterBuilder.GetProduct();
monsterGo.transform.SetParent(transform);
monsterGo.transform.position = mapMaker.monsterPathPos[0];
mMonsterIDIndex++;
}
//停止产生
public void StopCreateMonster()
{
CancelInvoke();
}
//增加当前回合数,并且交给下一个回合来处理产怪
public void AddRoundNum()
{
mMonsterIDIndex = 0;
killMonsterNum = 0;
level.AddRoundNum();
level.HandleRound();
//更新有关回合显示的UI
normalModelpanel.UpdatePanel();
}

/// <summary>
/// 与游戏处理逻辑有关的方法
/// </summary>

#if Game

//打开奖品页面
public void ShowPrizePage()
{
normalModelpanel.ShowPrizePage();
}

//开始游戏
public void StartGame()
{
isPause = false;
level.HandleRound();
}

//格子处理方法
public void HandleGrid(GridPoint grid)//当前选择的格子
{
if (grid.gridState.canBuild)
{
if (selectGrid==null)//没有上一个格子
{
selectGrid = grid;
selectGrid.ShowGrid();
PlayEffectMusic("NormalMordel/Grid/GridSelect");
}
else if (grid==selectGrid)//选中同一个格子
{
grid.HideGrid();
selectGrid = null;
PlayEffectMusic("NormalMordel/Grid/GridDeselect");
}
else if (grid!=selectGrid)//选中不同格子
{
selectGrid.HideGrid();
selectGrid = grid;
selectGrid.ShowGrid();
PlayEffectMusic("NormalMordel/Grid/GridSelect");
}
}
else
{
grid.HideGrid();
grid.ShowCantBuild();
PlayEffectMusic("NormalMordel/Grid/SelectFault");
if (selectGrid!=null)
{
selectGrid.HideGrid();
}
}
}
#endif
/// <summary>
/// 资源获取的有关方法
/// </summary>
/// <param name="resourcePath"></param>
/// <returns></returns>
public Sprite GetSprite(string resourcePath)
{
return mGameManager.GetSprite(resourcePath);
}
public AudioClip GetAudioClip(string resourcePath)
{
return mGameManager.GetAudioClip(resourcePath);
}
public RuntimeAnimatorController GetRuntimeAnimatorController(string resourcePath)
{
return mGameManager.GetRunTimeAnimatorController(resourcePath);
}
public GameObject GetGameObjectResource(string resourcePath)
{
return mGameManager.GetGameObjectResource(FactoryType.GameFactory,resourcePath);
}
public void PushGameObjectToFactory(string resourcePath,GameObject itemGo)
{
mGameManager.PushGameObjectToFactory(FactoryType.GameFactory,resourcePath,itemGo);
}

//播放特效音
public void PlayEffectMusic(string audioClipPath)
{
mGameManager.audioSourceManager.PlayEffectMusic(GetAudioClip(audioClipPath));
}
}
/// <summary>
/// 怪物
/// </summary>
public class Monster : MonoBehaviour
{

//属性值
public int monsterID;
public int HP;//总血量
public int currentHP;//当前血量
public float moveSpeed;//当前速度
public float initMoveSpeed;//初始速度
public int prize;//奖励金钱
//引用
private Animator animator;
private Slider slider;
//private GameController.Instance GameController.Instance;
private List<Vector3> monsterPointList;

//用于计数的属性或开关
private int roadPointIndex = 1;
private bool reachCarrot;//到达终点
private bool hasDecreasSpeed;//是否减速

private float decreaseSpeedTimeVal;//减速计时器
private float decreaseTime;//减速持续的具体时间

//资源
public AudioClip dieAudioClip;
public RuntimeAnimatorController runtimeAnimatorController;
private GameObject TshitGo;

private void Awake()
{
animator = GetComponent<Animator>();
slider = transform.Find("MonsterCanvas").Find("HPSlider").GetComponent<Slider>();
slider.gameObject.SetActive(false);
//GameController.Instance = GameController.Instance.Instance;
monsterPointList = GameController.Instance.mapMaker.monsterPathPos;
TshitGo = transform.Find("TShit").gameObject;
}

private void OnEnable()
{
monsterPointList = GameController.Instance.mapMaker.monsterPathPos;
//怪物的转向
if (roadPointIndex + 1 < monsterPointList.Count)
{
float xOffset = monsterPointList[0].x - monsterPointList[1].x;
if (xOffset < 0)//右走
{
transform.eulerAngles = new Vector3(0, 0, 0);
}
else if (xOffset > 0)
{
transform.eulerAngles = new Vector3(0, 180, 0);
}
}
}

private void Update()
{
if (GameController.Instance.isPause||GameController.Instance.gameOver)
{
return;
}
if (!reachCarrot)
{
transform.position = Vector3.Lerp(transform.position, monsterPointList[roadPointIndex],
1 / Vector3.Distance(transform.position, monsterPointList[roadPointIndex]) * Time.deltaTime * moveSpeed * GameController.Instance.gameSpeed);
if (Vector3.Distance(transform.position, monsterPointList[roadPointIndex]) <= 0.01f)
{
//怪物的转向
if (roadPointIndex + 1 < monsterPointList.Count)
{
float xOffset = monsterPointList[roadPointIndex].x - monsterPointList[roadPointIndex + 1].x;
if (xOffset < 0)//右走
{
transform.eulerAngles = new Vector3(0, 0, 0);
}
else if (xOffset > 0)
{
transform.eulerAngles = new Vector3(0, 180, 0);
}
}
slider.gameObject.transform.eulerAngles = Vector3.zero;
roadPointIndex++;
if (roadPointIndex >= GameController.Instance.mapMaker.monsterPathPos.Count)
{
reachCarrot = true;
}
}
}
else//到达终点
{
DestoryMonster();
//萝卜减血
GameController.Instance.DecreaseHP();
}

if (hasDecreasSpeed)
{
decreaseSpeedTimeVal += Time.deltaTime;
}
if (decreaseSpeedTimeVal >= decreaseTime)
{
CancelDecreaseDebuff();
decreaseSpeedTimeVal = 0;
}
}

//销毁怪物
private void DestoryMonster()
{
if (GameController.Instance.targetTrans==transform)
{
GameController.Instance.HideSignal();
}

if (!reachCarrot)//被玩家杀死的
{
//生成金币以及数目
GameObject coinGo = GameController.Instance.GetGameObjectResource("CoinCanvas");
coinGo.transform.Find("Emp_Coin").GetComponent<CoinMove>().prize = prize;
coinGo.transform.SetParent(GameController.Instance.transform);
coinGo.transform.position = transform.position;
//增加玩家的金币数量
GameController.Instance.ChangeCoin(prize);
//关于奖品的掉落
int randomNum = Random.Range(0,100);
if (randomNum<10)
{
GameObject prizeGo = GameController.Instance.GetGameObjectResource("Prize");
prizeGo.transform.position = transform.position-new Vector3(0,0,6);
GameController.Instance.PlayEffectMusic("NormalMordel/GiftCreate");
}
}
//产生销毁特效
GameObject effectGo = GameController.Instance.GetGameObjectResource("DestoryEffect");
effectGo.transform.SetParent(GameController.Instance.transform);
effectGo.transform.position = transform.position;
GameController.Instance.killMonsterNum++;
GameController.Instance.killMonsterTotalNum++;
InitMonsterGo();
GameController.Instance.PushGameObjectToFactory("MonsterPrefab", gameObject);

}

//初始化怪物的方法
private void InitMonsterGo()
{
monsterID = 0;
HP = 0;
currentHP = 0;
moveSpeed = 0;
roadPointIndex = 1;
dieAudioClip = null;
reachCarrot = false;
slider.value = 1;
slider.gameObject.SetActive(false);
prize = 0;
transform.eulerAngles = new Vector3(0, 0, 0);
decreaseSpeedTimeVal = 0;
decreaseTime = 0;
CancelDecreaseDebuff();
}

//承受伤害的方法
private void TakeDamage(int attackValue)
{
slider.gameObject.SetActive(true);
currentHP -= attackValue;
if (currentHP < 0)
{
//播放死亡音效
GameController.Instance.PlayEffectMusic("NormalMordel/Monster/"+GameController.Instance.currentStage.mBigLevelID.ToString()+"/"+monsterID.ToString());
DestoryMonster();
return;
}
slider.value = (float)currentHP / HP;
}

//减速buff的方法
private void DecreaseSpeed(BullectProperty bullectProperty)
{
if (!hasDecreasSpeed)
{
moveSpeed = moveSpeed - bullectProperty.debuffValue;
TshitGo.SetActive(true);
}
decreaseSpeedTimeVal = 0;
hasDecreasSpeed = true;
decreaseTime = bullectProperty.debuffTime;
}

//用来取消减速buff的方法
private void CancelDecreaseDebuff()
{
hasDecreasSpeed = false;
moveSpeed = initMoveSpeed;
TshitGo.SetActive(false);
}

//获取特异性属性的方法
public void GetMonsterProperty()
{
runtimeAnimatorController = GameController.Instance.controllers[monsterID - 1];
animator.runtimeAnimatorController = runtimeAnimatorController;
}

#if Game

private void OnMouseDown()
{
if (GameController.Instance.targetTrans == null)
{
GameController.Instance.targetTrans = transform;
GameController.Instance.ShowSignal();
}
//转换新目标
else if (GameController.Instance.targetTrans != transform)
{
GameController.Instance.HideSignal();
GameController.Instance.targetTrans = transform;
GameController.Instance.ShowSignal();
}
//两次点击的是同一个目标
else if (GameController.Instance.targetTrans == transform)
{
GameController.Instance.HideSignal();
}
}
#endif
}