https://www.bilibili.com/video/BV1Yq4y1S7zJ?p=1&vd_source=9728e0705d582ca9854cb5a50dd17fd8 莫新宇视频地址
![](https://i-blog.csdnimg.cn/blog_migrate/5b8411155d1157ddb2bb9d3f241d33a2.png)
usingSystem.Collections;
usingSystem.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TowerBuyer : MonoBehaviour {
//单例脚本,特点只挂一次
public static TowerBuyer instance;
[Header("炮塔预设体数组")]
public GameObject[] towerPrefabs;
[Header("游戏初始金钱")]
public int currentMoney = 300;
private int currentTowerIndex;
//显示金钱文本
private Text moneyText;
//游戏速度Toggle
private Toggle gameSpeedToggle;
//射线碰撞检测器
private RaycastHit hit;
//射线
private Ray ray;
private void Awake()
{
instance = this;
gameSpeedToggle =transform.GetChild(2).GetComponent<Toggle>();
moneyText = transform.Find("Coinicon/CoinText").GetComponent<Text>();
}
private void Start()
{
gameSpeedToggle.onValueChanged.AddListener(OnGameSpeedToggleValueChange);
UpdateMoney();
}
public void UpdateMoney() {
moneyText.text =currentMoney.ToString();
}
public void OnGameSpeedToggleValueChange(bool val) {
if (val)
{
Time.timeScale = 2;
}
else {
Time.timeScale = 1;
}
}
private void Update()
{
//将鼠标坐标转换成射线
ray =Camera.main.ScreenPointToRay(Input.mousePosition);
if (Input.GetMouseButtonDown(0) &&Physics.Raycast(ray, out hit)) {
if (!hit.collider.name.Contains("TowerBase")) {
return;
}
TowercrtTowerPrefab=towerPrefabs[currentTowerIndex].GetComponent<Tower>();
//如果钱不够
if (currentMoney < crtTowerPrefab.towerCost){
Debug.Log("钱不够!!!");
return;
}
//先交钱
currentMoney -=crtTowerPrefab.towerCost;
//更新
UpdateMoney();
//生成炮塔
GameObjectcrtTower=Instantiate(towerPrefabs[currentTowerIndex]);
//设置父对象
crtTower.transform.SetParent(hit.collider.transform);
//调整本地坐标
crtTower.transform.localPosition=Vector3.up*1.2f;
}
}
/// <summary>
/// 炮塔按钮点击事件
/// </summary>
/// <param name="towerIndex"></param>
public void OnTowerButtonClick(int towerIndex) {
//设置当前点击的炮塔编号
currentTowerIndex =towerIndex;
}
}
usingSystem.Collections;
usingSystem.Collections.Generic;
using UnityEngine;
public class Tower : MonoBehaviour {
[Header("炮塔价格")]
public int towerCost = 200;
[Header("炮塔主体")]
public Transform turrent;
[Header("转向速度")]
public float turnSpeed = 5f;
[Header("炮弹预设体")]
public GameObject bulletPrefab;
[Header("开炮时间间隔")]
public float fireInterval=2;
[Header("炮弹生成点")]
public Transform firePoint;
[Header("炮塔炮弹伤害")]
public float damage = 100;
private float timer;
//炮塔的攻击列表
private List<Monster> monsterList;
private void Awake()
{
monsterList = newList<Monster>();
}
private void Update()
{
if (monsterList.Count == 0)
return;
//炮塔指向怪物的方向向量
Vector3 dir = monsterList[0].transform.position+ Vector3.up*monsterList[0].monsterHeight - turrent.position;
//转换四元数
Quaternion targetQua =Quaternion.LookRotation(dir);
turrent.rotation =Quaternion.Lerp(turrent.rotation,targetQua,Time.deltaTime*turnSpeed);
timer += Time.deltaTime;
if (timer > fireInterval) {
//生成炮弹
GameObjectblt=Instantiate(bulletPrefab, firePoint.position, Quaternion.identity);
//初始化炮弹
blt.GetComponent<Bullet>().BulletInit(monsterList[0].transform,damage);
//归零计时器
timer = 0;
}
}
public void RemoveMonsterFromList(Monster monster) {
if (monsterList.Contains(monster)) {
//从列表中移除
monsterList.Remove(monster);
}
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Monster") {
//当前怪物
Monster currentMonster =other.GetComponent<Monster>();
//加入攻击列表
monsterList.Add(other.GetComponent<Monster>());
//给怪物绑定死亡事件
currentMonster.deathEvent+= RemoveMonsterFromList;
}
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "Monster")
{
//当前怪物
Monster currentMonster =other.GetComponent<Monster>();
//从攻击列表移除
monsterList.Remove(other.GetComponent<Monster>());
//给怪物解除绑定死亡事件
currentMonster.deathEvent -= RemoveMonsterFromList;
}
}
}
usingSystem.Collections;
usingSystem.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using System;
public class Monster : MonoBehaviour {
[Header("怪物血量")]
public float monsterHP;
[Header("怪物身高")]
public float monsterHeight = 0.5f;
[HideInInspector]
//击杀怪物的价值
private int monsterValue;
/// <summary>
/// 死亡事件
/// </summary>
public Action<Monster> deathEvent;
private NavMeshAgent nav;
private Animator ani;
private CapsuleCollider col;
private void Awake()
{
nav =GetComponent<NavMeshAgent>();
ani =GetComponent<Animator>();
col =GetComponent<CapsuleCollider>();
}
/// <summary>
/// 怪物初始化
/// </summary>
/// <param name="moveSpeed"></param>
/// <param name="hp"></param>
/// <param name="target"></param>
public void MonsterInit(float moveSpeed, float hp, int monsterValue ,Vector3 target) {
nav.speed = moveSpeed;
monsterHP = hp;
this.monsterValue = monsterValue;
nav.SetDestination(target);
}
public void TakeDamage(float damage) {
//扣血
monsterHP -= damage;
if (monsterHP > 0)
{
//活着,播放受伤动画
ani.SetTrigger("Damage");
//停止导航
nav.isStopped = true;
//延时恢复导航
Invoke("ResumeNavigation",0.25f);
}
else {
//获取怪物的价值
TowerBuyer.instance.currentMoney += monsterValue;
TowerBuyer.instance.UpdateMoney();
//播放死亡动画
ani.SetTrigger("Dead");
//停止导航
nav.isStopped = true;
if (deathEvent != null)
{
//执行死亡事件
deathEvent(this);
}
//关闭碰撞体
col.enabled = false;
Destroy(gameObject,0.9f);
}
}
/// <summary>
/// 恢复导航
/// </summary>
private void ResumeNavigation() {
nav.isStopped = false;
}
}
usingSystem.Collections;
usingSystem.Collections.Generic;
using UnityEngine;
public class GameHealth : MonoBehaviour {
[Header("游戏血量")]
public int gameHealth = 10;
private void OnTriggerEnter(Collider other)
{
//销毁游戏对象
Destroy(other.gameObject);
if (other.tag == "Monster") {
if (--gameHealth == 0) {
Debug.Log("GameOver");
}
}
}
}
usingSystem.Collections;
usingSystem.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour {
//虚拟轴
private float hor, ver;
[Header("起结界始")]
Vector2 startLimit = new Vector2(20,0);
[Header("终点界始")]
Vector2 endLimit = new Vector2(40, 60);
[Header("移动速度")]
public float moveSpeed = 3f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
hor = Input.GetAxis("Horizontal");
ver = Input.GetAxis("Vertical");
//获取当前摄像机可能的位置
Vector3crtPos=transform.position + new Vector3(hor, 0, ver) * Time.deltaTime * moveSpeed;
float x = Mathf.Clamp(crtPos.x, startLimit.x,endLimit.x);
float z = Mathf.Clamp(crtPos.z, startLimit.y,endLimit.y);
transform.position = new Vector3(x,crtPos.y, z);
}
}
usingSystem.Collections;
usingSystem.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour {
//追踪目标
private Transform target;
[Header("追踪速度")]
public float speed = 5f;
//炮塔的伤害
private float damage = 100;
/// <summary>
/// 炮弹信息初始化
/// </summary>
/// <paramname="target"></param>
/// <paramname="damage"></param>
public void BulletInit(Transform target,float damage) {
this.target = target;
this.damage = damage;
}
private void Update()
{
if (target == null)
{
//销毁自己
Destroy(gameObject);
return;
}
transform.position =Vector3.Lerp(transform.position, target.position, Time.deltaTime * speed);
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Monster") {
//扣血
other.GetComponent<Monster>().TakeDamage(100);
//销毁自己
Destroy(gameObject);
}
}
}
usingSystem.Collections;
usingSystem.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
/// <summary>
/// 怪物波次信息
/// </summary>
[System.Serializable]//序列化
public class MonsterWave {
[Header("波次之间的时间间隔")]
public float waveInterval;
[Header("怪物之间的时间间隔")]
public float monsterInterval;
[Header("怪物个数")]
public int monsterCount;
[Header("怪物预设体")]
public GameObject monsterPrefab;
[Header("怪物血量")]
public float monsterHP;
[Header("怪物移动速度")]
public float monsterNavSpeed;
[Header("击杀怪物的价值")]
public int monsterValue;
}
public class MonsterCreater : MonoBehaviour {
[Header("波次信息")]
public MonsterWave[] waves;
//波次计数器
private float wavetimer=0;
//怪物生成计时器
private float monsterTimer = 0;
//怪物生成计数器
private int counter=0;
//当前生成的波次编号
private int waveIndex=0;
//起点
private Transform startTra;
//终点
private Transform endTra;
private void Awake()
{
startTra = GameObject.FindWithTag("Start").transform;
endTra =GameObject.FindWithTag("End").transform;
}
private void Update()
{
//波次计时器计时
wavetimer += Time.deltaTime;
//如果所有波次怪物都已经生成完毕
if (waveIndex >= waves.Length) {
return;
}
//计时达到该生成这波怪的时候
if (wavetimer >waves[waveIndex].waveInterval) {
for (int i = 0; i<waves[waveIndex].monsterCount; i++) {
//怪物计时器计时
monsterTimer +=Time.deltaTime;
//当前波次的怪物是否生成完毕
if (counter <waves[waveIndex].monsterCount)
{
//计时达到生产怪物的时间间隔
if (monsterTimer> waves[waveIndex].monsterInterval)
{
//生成怪物
GameObjectcurrentMonster = Instantiate(waves[waveIndex].monsterPrefab, startTra.position,Quaternion.identity);
//设置当前怪物的导航速度
currentMonster.GetComponent<NavMeshAgent>().speed =waves[waveIndex].monsterNavSpeed;
//初始化怪物信息
currentMonster.GetComponent<Monster>().MonsterInit(waves[waveIndex].monsterNavSpeed,waves[waveIndex].monsterHP, waves[waveIndex].monsterValue, endTra.position);
//计数器递增
counter++;
//计时器归零
monsterTimer = 0;
}
}
//当前波次怪物都已经生成完毕
else {
//波次编号递增
waveIndex++;
//计数器归零
counter = 0;
//波次计数器归零
wavetimer = 0;
}
}
}
}
}