| 项目 Project | 视图 View |
| 游戏对象 GameObject | 刚体 Rigidbody |
| 组件 Component | 碰撞 Collide |
| 预制件 Prefab | 材质 Material |
| 脚本 Script | 资源商店 Asset Store |
| 调试 Debug | 音频 Audio |
| 包 Package | 发布 Publish |
| 导航 Navigation | 用户界面 Toggle |
| 物理 Physical | 线渲染 Line Renderer |
| 协程 Coroutine | 数据脚本 Data |




using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;//引入事件系统
public class Base : MonoBehaviour
{
MeshRenderer m_Renderer;
Color init_Color;
public Color hover_Color;
void Start()
{
m_Renderer = GetComponent<MeshRenderer>();
init_Color = m_Renderer.material.color;
}
private void OnMouseEnter()
{
if (!EventSystem.current.IsPointerOverGameObject())//增加判断:不在UI上
{
m_Renderer.material.color = hover_Color;
}
}
private void OnMouseExit()
{
m_Renderer.material.color = init_Color;
}
}






using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;
public class Mon : MonoBehaviour
{
public GameObject explosion;
public float Hp;
public Image HpBar;
NavMeshAgent agent;
Transform tar;
float curHealth;
float oriSpeed;
void Start()
{
curHealth = Hp;
agent = GetComponent<NavMeshAgent>();
tar = GameObject.FindGameObjectWithTag("target").transform;
oriSpeed = agent.speed;
}
void Update()
{
agent.SetDestination(tar.position);
//请根据实际情况判断距离
if (Vector3.Distance(agent.destination, agent.nextPosition) <= 0.5f)
{
Destroy(gameObject);//1
//每成功达到终点1个怪物,玩家生命减1;来自脚本GameManager.cs
GameManager.lives--;
}
}
//供子弹脚本的碰撞处理使用
public void GetDam(float dam)
{
curHealth -= dam;
HpBar.fillAmount = curHealth / Hp;
if (curHealth <= 0)
{
Destroy(gameObject);//2
//播放死亡时的粒子特效,参见后面[提高]部分
GameObject exp = Instantiate(explosion);
Destroy(exp, 1);
}
}
//后期预留减速功能
public void getSlow(float factor)
{
agent.speed = oriSpeed * (1 - factor);
StartCoroutine(clearSlow());
}
public void resetSlow()
{
agent.speed = oriSpeed;
}
IEnumerator clearSlow()
{
yield return new WaitForSeconds(2);
resetSlow();
}
//业务整合或单独写在对象销毁所在的函数内1、2
private void OnDestroy()
{
Spawn.alive--;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Data
{
public GameObject monPrefab;
public int monNum;
public int monInter;
}
//Spawn.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawn : MonoBehaviour
{
public Data[] mons;
public float waveInter;
public static int alive = 0;
public static bool isDone=false;
void Start()
{
isDone = false;
StartCoroutine(MonSpawn());
}
IEnumerator MonSpawn()
{
for (int i = 0; i < mons.Length; i++)
{
for (int j = 0; j < mons[i].monNum; j++)
{
alive++;
GameObject mon = Instantiate(mons[i].monPrefab, transform.position, Quaternion.identity);
yield return new WaitForSeconds(mons[i].monInter);
}
while (alive > 0)
{
yield return null;
}
yield return new WaitForSeconds(waveInter);
}
isDone=true;
}
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;//引入UI事件系统
public class Build : MonoBehaviour
{
public GameObject standard, missile, laser;
GameObject selected;
void Start()
{
selected = standard;
}
void Update()
{
//按下鼠标且不在UI上
if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject())
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
//和指定层发射碰撞
//如果不指定距离,会放到路面上!!!
if (Physics.Raycast(ray, out hit, 1000, LayerMask.GetMask("base")))
{
GameObject obj = hit.collider.gameObject;
//如果当前对象没有炮塔/子对象;且金钱足够[功能预留]
if (obj.transform.childCount == 0)
{
//动态生成并放置炮塔,成为基座base的子对象
GameObject tower = Instantiate(selected, obj.transform.position, Quaternion.identity);
tower.transform.parent = obj.transform;
}
}
}
}
public void selTowerStandard(bool isON)//选中第1种炮:标准炮
{
if (isON)
{
selected = standard;
}
}
public void selTowerMissile(bool isON)//选中第2种炮:火箭炮
{
if (isON)
{
selected = missile;
}
}
public void selTowerLaser(bool isON)//选中第3种炮:激光炮
{
if (isON)
{
selected = laser;
}
}
}
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
GameObject obj = hit.collider.gameObject;
if (obj.tag == "base" && obj.transform.childCount == 0)
{
GameObject tar = Instantiate(curTower, obj.transform.position, Quaternion.identity);
tar.transform.parent = obj.transform;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class Base : MonoBehaviour
{
public GameObject towerFab;
private void OnMouseDown()
{
if (transform.childCount == 0 && !EventSystem.current.IsPointerOverGameObject())
{
GameObject obj = Instantiate(towerFab, transform.position, Quaternion.identity);
obj.transform.parent = transform;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
public float damage = 10;
public float speed = 20;
Transform target = null;
void Update()
{
if (target == null)
{
Destroy(gameObject);
return;
}
transform.Translate(Vector3.forward * speed * Time.deltaTime);
transform.LookAt(target.position);
}
public void SetTarget(Transform tar)
{
target = tar;
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "mon")
{
Destroy(gameObject);
target.GetComponent<Mon>().GetDam(damage);
//预留:粒子击中特效
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Standard : MonoBehaviour
{
public List<GameObject> list = new List<GameObject>();
public GameObject bullet;
public Transform firePos;
public Transform headRot;
Transform target;//也可以声明为GameObj,但是我们仅仅需要的是一个位置
public float attackInter = 1f;
float timer = 0;
private void Start()
{
InvokeRepeating("GetTarget", 0, 0.5f);
}
void Update()
{
if (target == null)
{
return;
}
//创建新的位置信息,主要是控制高度一致,避免后仰前俯;且让炮台始终朝向目标
Vector3 tarPos = target.position;
tarPos.y = headRot.position.y;
headRot.LookAt(tarPos);
timer += Time.deltaTime;
if (timer >= attackInter && list.Count > 0)
{
GameObject bulletObj = Instantiate(bullet, firePos.position, firePos.rotation);
bulletObj.GetComponent<Bullet>().SetTarget(target);
Destroy(bulletObj.gameObject, 5);
timer = 0;
}
}
void GetTarget()
{
float minDis = Mathf.Infinity;
//起始必须赋空值
Transform nearMon = null;
//MUST:每次获取前先把可能的空对象移出
list.RemoveAll(item => item == null);
foreach (GameObject item in list)
{
float dis = Vector3.Distance(transform.position, item.transform.position);
if (dis < minDis)
{
minDis = dis;
nearMon = item.transform;
}
}
target = nearMon;
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "mon")
{
list.Add(other.gameObject);
}
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "mon")
{
list.Remove(other.gameObject);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Laser : MonoBehaviour
{
public List<GameObject> list = new List<GameObject>();
public Transform firePos;
public Transform headRot;
Transform target;
public LineRenderer line;
public float damOverTime = 20f;
public float slowFactor = 0.6f;
private void Start()
{
InvokeRepeating("GetTarget", 0, 0.5f);
}
void Update()
{
if (target == null)
{
line.enabled = false;
return;
}
Vector3 tarPos = target.position;
tarPos.y = headRot.position.y;
line.enabled = true;
headRot.LookAt(tarPos);
line.SetPositions(new Vector3[] { firePos.position,target.position});
target.GetComponent<Mon>().GetDam(damOverTime*Time.deltaTime);
target.GetComponent<Mon>().getSlow(slowFactor);
//发射音效
}
void GetTarget()
{
float minDis = Mathf.Infinity;
Transform nearMon = null;
//MUST:每次获取前先把可能的空对象移出
list.RemoveAll(item => item == null);
foreach (GameObject item in list)
{
float dis = Vector3.Distance(transform.position, item.transform.position);
if (dis < minDis)
{
minDis = dis;
nearMon = item.transform;
}
}
target = nearMon;
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "mon")
{
list.Add(other.gameObject);
}
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "mon")
{
list.Remove(other.gameObject);
}
}
}
//Menu.cs
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Menu : MonoBehaviour
{
public Animation ani;
private void Start()
{
Time.timeScale = 1;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
Application.Quit();
}
}
public void LoadScene(string str)
{
SceneManager.LoadScene(str);
}
public void Quit()
{
Application.Quit();
}
public void LoadAnim()
{
ani.Play();
}
}
//GameManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public static int lives = 3;
public GameObject failEnding;
public GameObject winEnding;
public GameObject pauseEnding;
bool isPause=false;
private void Start()
{
lives = 3;
Time.timeScale = 1;
failEnding.SetActive(false);
winEnding.SetActive(false);
pauseEnding.SetActive(false);
}
private void Update()
{
//失败
if (lives <= 0)
{
failEnding.SetActive(true);
Time.timeScale = 0;
}
//胜利
if (lives > 0 && Spawn.isDone)
{
StartCoroutine(dis());
}
//按下Escape
if (Input.GetKeyDown(KeyCode.Escape))
{
if (isPause)
{
isPause = false;
Time.timeScale = 1;
pauseEnding.SetActive(false);
}
else
{
isPause = true;
Time.timeScale = 0;
pauseEnding.SetActive(true);
}
}
}
public void backToGame()
{
Time.timeScale = 1;
pauseEnding.SetActive(false);
isPause = false;
}
public void LoadScene(string str)
{
SceneManager.LoadScene(str);
}
public void Quit()
{
Application.Quit();
}
//暂停1秒后显示winEnding
IEnumerator dis()
{
yield return new WaitForSeconds(1);
winEnding.SetActive(true);
}
}
public AudioSource player; public AudioClip clip; // player.PlayOneShot(clip);
public AudioSource player;
public AudioClip clip;
//如果没有播放就播放,否则什么也不做
if (player.isPlaying)
{
}
else
{
player.PlayOneShot(clip);
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioCtrl : MonoBehaviour
{
public static AudioCtrl instance;
AudioSource player;
private void Awake()
{
if (instance == null)
{
instance = this;
}
else if (instance != this)
{
Destroy(gameObject);
}
DontDestroyOnLoad(gameObject);
}
void Start()
{
player = GetComponent<AudioSource>();
}
public void playAudio(AudioClip clip)
{
player.PlayOneShot(clip);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class xxx : MonoBehaviour
{
public AudioClip clip;
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "mon")
{
//其它业务略
AudioCtrl.instance.playAudio(clip);
}
}
}

















