Chinar堅持將簡單的生活方式,帶給世人! (擁有更好的閱讀體驗 —— 高分辨率用戶請根據需求調整網頁縮放比例) |
1
有耐心的朋友可以跳轉到SiKi學院,觀看視頻:SiKi學院
SiKi學院——是本人發現的網絡教程做的很完善的網絡課堂,推薦大家多學,多看
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/// <summary>
/// 建築物控制腳本
/// </summary>
public class BuildManager : MonoBehaviour
{
public TurretData StandarTurretData; //標准炮塔數據
public TurretData MissileTurretData; //導彈炮塔數據
public TurretData LaserTurretData; //激光炮塔數據
private TurretData SelectedTurretData; //當前選擇的炮塔(即將要建造的炮台)
private MapCube _selectedMapCube; //當前選擇的游戲炮台
private int Money = 1000; //金幣
public Text MoneyText; //金幣文本框
public Animator MoneyAnimator;
public GameObject UpgradeCanvas;
public Button ButtonUpGrade;
private Animator UpgradeCanvasAnimator;
void Start()
{
UpgradeCanvasAnimator = UpgradeCanvas.GetComponent<Animator>();
}
void Update()
{
//容錯,炮台的建造,需要滿足2個條件
if (SelectedTurretData != null && Input.GetMouseButtonDown(0)) //如果鼠標右鍵按下;
{
if (EventSystem.current.IsPointerOverGameObject() == false) //檢測鼠標在不在UI上。
{
//射線
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//被照射物體
RaycastHit hit;
//是否照射到物體 (射線,被照射物體,射線長度,MapCuber層的物體)
bool isCollider = Physics.Raycast(ray, out hit, 1000, LayerMask.GetMask("MapCube"));
if (isCollider)
{
MapCube mapcube = hit.collider.GetComponent<MapCube>(); //得到點擊的mapcube
//如果底板上 沒有炮塔,則可以創建
if (mapcube.TurretGo == null)
{
//可以創建,然后判斷錢夠不夠,
if (Money >= SelectedTurretData.Cost)
{
ChangeMoney(-SelectedTurretData.Cost); //減少錢
mapcube.BuildTurret(SelectedTurretData); //創建炮塔
}
else
{
//提示錢不夠
MoneyAnimator.SetTrigger("Flicker");
}
}
else if (mapcube.TurretGo != null)
{
//選擇的是否是同一個炮台&&UI升級框是否顯示
if (mapcube.TurretGo == _selectedMapCube && UpgradeCanvas.activeInHierarchy)
{
StartCoroutine(HideUpGradeUi());
}
else
{
Vector3 upgraded = new Vector3(mapcube.transform.position.x, mapcube.transform.position.y + 2.6f, mapcube.transform.position.z);
//升級
ShowUpGradeUI(upgraded, mapcube.IsUpgraded);
}
//選擇的炮台,被賦值
_selectedMapCube = mapcube;
}
}
}
}
}
public void OnStandarSelected(bool isOn)
{
if (isOn)
{
SelectedTurretData = StandarTurretData;
}
}
public void OnMissileSelected(bool isOn)
{
if (isOn)
{
SelectedTurretData = MissileTurretData;
}
}
public void OnLaserSelected(bool isOn)
{
if (isOn)
{
SelectedTurretData = LaserTurretData;
}
}
/// <summary>
/// 金錢的變動
/// </summary>
/// <param name="change"></param>
private void ChangeMoney(int change = 0)
{
Money += change; //金幣的變動
MoneyText.text = "¥" + Money; //金幣文本框賦值
}
/// <summary>
/// 顯示升級按鈕
/// </summary>
/// <param name="pos"></param>
/// <param name="isDisableUp"></param>
private void ShowUpGradeUI(Vector3 pos, bool isDisableUp = false) //是否禁用升級按鈕
{
StopCoroutine(HideUpGradeUi());
UpgradeCanvas.SetActive(false); //顯示按鈕
UpgradeCanvas.transform.position = pos;
UpgradeCanvas.SetActive(true); //顯示按鈕
ButtonUpGrade.interactable = !isDisableUp; //是否可以交互/ false
}
/// <summary>
/// 隱藏升級按鈕
/// </summary>
IEnumerator HideUpGradeUi()
{
UpgradeCanvasAnimator.SetTrigger("Hide");
yield return new WaitForSeconds(0.6f);
UpgradeCanvas.SetActive(false);
}
/// <summary>
/// 點擊升級按鈕,升級炮塔
/// </summary>
public void OnUpGradeButtonDown()
{
if (Money >= _selectedMapCube._turretData.Cost) //錢夠不夠
{
ChangeMoney(-_selectedMapCube._turretData.Cost);
_selectedMapCube.UpGradeTurret();
}
else
{
MoneyAnimator.SetTrigger("Flicker");
}
StartCoroutine(HideUpGradeUi());
}
/// <summary>
/// 點擊拆按鈕。拆炮塔
/// </summary>
public void OnDestroyButtonDown()
{
_selectedMapCube.DestroyTurret();
StartCoroutine(HideUpGradeUi());
}
}
2
using UnityEngine;
/// <summary>
/// 子彈類腳本
/// </summary>
public class Bullet : MonoBehaviour
{
public int Damage = 50; //傷害
public float Speed = 20; //速度
private Transform Target; //目標
public GameObject ExplosionEffectPrefab; //子彈特效
private float DistanceArriveTarget = 2; //子彈於目標物體,向量長度
void Start()
{
}
void Update()
{
if (Target == null)
{
Die();
return;
}
transform.LookAt(Target.position); //面向目標位置
transform.Translate(Vector3.forward * Speed * Time.deltaTime);
Vector3 dir = Target.position - transform.position;
if (dir.magnitude < DistanceArriveTarget) //向量的長度magnitude
{
//子彈打到敵人,掉血
Target.GetComponent<Enemy>().TakeDamage(Damage);
Die();
}
}
private void Die()
{
//實例化特效
GameObject effect = Instantiate(ExplosionEffectPrefab, transform.position, transform.rotation) as GameObject;
//刪除特效
Destroy(effect, 1f);
//銷毀子彈
Destroy(this.gameObject);
}
/// <summary>
/// 設置目標
///
/// </summary>
/// <param name="_target"></param>
public void SetTarget(Transform _target)
{
this.Target = _target;
}
}
3
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
/// <summary>
/// 敵人腳本
/// </summary>
public class Enemy : MonoBehaviour
{
//位置數組
private Transform[] positions;
//下標,從0開始
private int index = 0;
//速度
public float Speed = 10;
public float Hp = 150;
private float TotalHp; //總HP
public GameObject ExplosionEffect; //敵人爆炸特效
private Slider HpSlider;
void Start()
{
positions = WayPoints.positions;
TotalHp = Hp;
HpSlider = GetComponentInChildren<Slider>();
}
void Update()
{
Move();
}
void Move()
{
//下標越界,就跳出;
if (index > positions.Length - 1) return;
//找一個方向,(目標位置-當前位置).normalized 取得這個向量的單位向量 ;
transform.Translate((positions[index].position - transform.position).normalized * Time.deltaTime * Speed);
//判斷 兩點 之間的距離
if (Vector3.Distance(positions[index].position, transform.position) < 0.5f)
{
index++;
}
if (index > positions.Length - 1)
{
ReachDestination();
}
}
/// <summary>
/// ReachDestination 到達 目的地 銷毀
/// </summary>
void ReachDestination()
{
Destroy(this.gameObject);
GameManager.instance.Failed();
}
/// <summary>
/// 監聽銷毀敵人
/// </summary>
void OnDestroy()
{
EnemySpawner.CountEnemyAlive--;
}
/// <summary>
/// 敵人受到傷害
/// </summary>
/// <param name="damage"></param>
public void TakeDamage(float damage)
{
if (Hp <= 0) return; //死了不處理
Hp -= damage; //減少血量
HpSlider.value = (float) Hp / TotalHp; //血條
if (Hp <= 0)
{
Die();
}
}
private void Die()
{
GameObject effect = Instantiate(ExplosionEffect, transform.position, transform.rotation) as GameObject;
Destroy(effect, 1.5f);
Destroy(this.gameObject);
}
}
4
using UnityEngine;
using System.Collections;
/// <summary>
/// 敵人生成控制腳本
/// </summary>
public class EnemySpawner : MonoBehaviour
{
//屬性面板
public Wave[] Waves;
//生成位置
public Transform StartTran;
//孵化間隔
public float WaveRate = 0.2f;
//存活敵人的數量
public static int CountEnemyAlive = 0;
private Coroutine coroutine;
void Start()
{
coroutine = StartCoroutine(SpawnEnemy());
}
/// <summary>
/// 敵人孵化器
/// </summary>
/// <returns></returns>
IEnumerator SpawnEnemy()
{
//遍歷所有Waves中的 數組
foreach (Wave wave in Waves)
{
for (int i = 0; i < wave.Count; i++)
{
//實例化預設物(每一波敵人的預設物,開始位置,無旋轉的)旋轉前的初始角
GameObject.Instantiate(wave.EnemyPrefab, StartTran.position, Quaternion.identity);
CountEnemyAlive++; //存活數量增加
if (i != wave.Count - 1) //檢測生成是否完畢
{
//時間間隔
yield return new WaitForSeconds(wave.Rate);
}
}
//當存活數量大於0
while (CountEnemyAlive > 0)
{
yield return 0; //暫停0幀,不執行下邊代碼
}
//每一波暫停 WaveRate 秒
yield return new WaitForSeconds(WaveRate);
}
}
/// <summary>
/// 停止生成
/// </summary>
public void Stop()
{
StopCoroutine(coroutine);
}
}
5
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// 地圖版塊控制腳本
/// </summary>
public class MapCube : MonoBehaviour
{
[HideInInspector] //不顯示在 Inspector 面板
public GameObject TurretGo; //保存當前Cube身上的炮台
[HideInInspector] public TurretData _turretData;
public GameObject BuildEffect;
private Renderer CubeRenderer;
[HideInInspector] public bool IsUpgraded; //MapCub上的炮塔是否升級過
void Start()
{
CubeRenderer = GetComponent<Renderer>();
}
/// <summary>
/// 點擊創建炮塔
/// </summary>
/// <param name="turretPrefab"></param>
public void BuildTurret(TurretData turretData)
{
this._turretData = turretData;
IsUpgraded = false;
//創建炮塔,位置,旋轉,強轉
TurretGo = Instantiate(turretData.TurretPrefab, transform.position, Quaternion.identity) as GameObject;
GameObject effectobj = Instantiate(BuildEffect, transform.position, Quaternion.identity) as GameObject;
Destroy(effectobj, 1f);
}
/// <summary>
/// 升級炮台
/// </summary>
/// <param name="turretgo"></param>
public void UpGradeTurret()
{
if (IsUpgraded == true) return; //容錯
Destroy(TurretGo); //刪除低級炮塔
IsUpgraded = true; //升級狀態變化
//創建炮塔,位置,旋轉,強轉
TurretGo = Instantiate(_turretData.TurretUpGradedPrefab, transform.position, Quaternion.identity) as GameObject;
GameObject effectobj = Instantiate(BuildEffect, transform.position, Quaternion.identity) as GameObject;
}
/// <summary>
/// 拆除炮台
/// </summary>
public void DestroyTurret()
{
Destroy(TurretGo);
GameObject effectobj = Instantiate(BuildEffect, transform.position, Quaternion.identity) as GameObject;
IsUpgraded = false; //升級狀態變化
TurretGo = null;
_turretData = null;
}
/// <summary>
/// 鼠標移入
/// </summary>
private void OnMouseEnter()
{
//Cube上沒有炮台,且,鼠標沒有放在UI上
if (TurretGo == null && EventSystem.current.IsPointerOverGameObject() == false)
{
CubeRenderer.material.color = Color.red; //變紅
}
}
/// <summary>
/// 鼠標移出
/// </summary>
private void OnMouseExit()
{
CubeRenderer.material.color = Color.white; //變紅
}
}
6
using UnityEngine;
/// <summary>
/// 炮塔模型類
/// </summary>
[System.Serializable] //可序列化
public class TurretData
{
//炮塔預設物
public GameObject TurretPrefab;
//花費
public int Cost;
//炮塔升級預設物
public GameObject TurretUpGradedPrefab;
//升級炮塔花費
public int CostUpGraded;
//默認枚舉類型
public TurretType Type;
}
/// <summary>
/// 枚舉一個炮塔類
/// </summary>
public enum TurretType
{
StandardTurret, //標准
MissileTurret, //導彈
LaserTurret //激光
}
7
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 炮塔控制腳本類
/// </summary>
public class Turret : MonoBehaviour
{
private List<GameObject> Enemys = new List<GameObject>(); //進入方位的敵人
public float AttackRateTime = 1; //攻擊間隔
private float Timer = 0; //計時器
public GameObject BulletPrefab; //子彈 預設物
public Transform FirePos;
public Transform Head;
public bool UseLaser = false; //默認攻擊方式
public float DamageRate = 70; //激光炮塔,持續傷害 速率。每秒70點傷害
public LineRenderer LaseRenderer;
public GameObject LaserEffect; //激光特效
void Start()
{
Timer = AttackRateTime;
}
void Update()
{
if (Enemys.Count > 0 && Enemys[0] != null)
{
Vector3 targetPosition = Enemys[0].transform.position;
targetPosition.y = Head.position.y;
Head.LookAt(targetPosition);
}
if (UseLaser == false)
{
Timer += Time.deltaTime;
//敵人數量大於0,且滿足間隔時間
if (Enemys.Count > 0 && Timer >= AttackRateTime)
{
Timer = 0;
Attack();
}
}
else if (Enemys.Count > 0)
{
if (LaseRenderer.enabled == false) LaseRenderer.enabled = true;
if (Enemys[0] == null)
{
UpDateEnemys();
}
if (Enemys.Count > 0)
{
//激光炮塔朝向
LaseRenderer.SetPositions(new Vector3[] {FirePos.position, Enemys[0].transform.position});
//激光炮塔攻擊
Enemys[0].GetComponent<Enemy>().TakeDamage(DamageRate * Time.deltaTime);
LaserEffect.SetActive(true);
LaserEffect.transform.position = Enemys[0].transform.position;
//激光特效,朝向炮塔
Vector3 pos = transform.position;
pos.y = Enemys[0].transform.position.y;
LaserEffect.transform.LookAt(pos);
}
}
else
{
LaserEffect.SetActive(false);
LaseRenderer.enabled = false;
}
}
/// <summary>
/// 攻擊方法
/// </summary>
private void Attack()
{
if (Enemys[0] == null)
{
UpDateEnemys();
}
if (Enemys.Count > 0)
{
//實例化子彈
GameObject bullet = Instantiate(BulletPrefab, FirePos.position, FirePos.rotation) as GameObject;
//子彈 指向目標
bullet.GetComponent<Bullet>().SetTarget(Enemys[0].transform);
}
else
{
Timer = AttackRateTime; //下次來敵人,直接攻擊
}
}
/// <summary>
/// 進入區域
/// </summary>
/// <param name="col"></param>
private void OnTriggerEnter(Collider col)
{
if (col.tag == "Enemy")
{
Enemys.Add(col.gameObject);
}
}
/// <summary>
/// 離開區域
/// </summary>
/// <param name="col"></param>
private void OnTriggerExit(Collider col)
{
if (col.tag == "Enemy")
{
Enemys.Remove(col.gameObject);
}
}
/// <summary>
/// 更新集合
/// </summary>
private void UpDateEnemys()
{
//用來存空元素下標 的數組
List<int> EmptyIndex = new List<int>();
//移除所有為空的元素,遍歷進入范圍的敵人數組長度。
for (int i = 0; i < Enemys.Count; i++)
{
if (Enemys[i] == null)
{
EmptyIndex.Add(i);
}
}
//移除 所有空元素
for (int i = 0; i < EmptyIndex.Count; i++)
{
//由於Enemys移除元素,下標會變動。所以減去,移除的個數;
Enemys.RemoveAt(EmptyIndex[i] - i);
}
}
}
8
using UnityEngine;
using System.Collections;
/// <summary>
/// 玩家視角控制腳本
/// </summary>
public class ViewController : MonoBehaviour
{
public float Speed = 1; //速度
public float MouseSpeed = 249; //速度
void Start()
{
}
void Update()
{
//獲取水平和垂直參數
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
float mouse = Input.GetAxis("Mouse ScrollWheel") * MouseSpeed;
//控制移動,並根據時間平滑移動,根據世界坐標移動
transform.Translate(new Vector3(h * Speed, mouse, v * Speed) * Time.deltaTime, Space.World);
}
}
9
using UnityEngine;
/// <summary>
/// 保存每一波敵人生成所需要的屬性
/// </summary>
[System.Serializable] //可以被序列化的屬性
public class Wave
{
public GameObject EnemyPrefab; //敵人
public int Count; //數量
public float Rate; //時間間隔
}
10
有耐心的朋友可以跳轉到SiKi學院,觀看視頻:SiKi學院
using UnityEngine;
/// <summary>
/// 路徑導航腳本
/// </summary>
public class WayPoints : MonoBehaviour
{
//拐點,數組
public static Transform[] positions;
void Awake()
{
//找到當前,掛載腳本物體下的,子物體數量
positions = new Transform[transform.childCount];
//依次遍歷所有子物體,得到依次的位置
for (int i = 0; i < positions.Length; i++)
{
positions[i] = transform.GetChild(i);
}
}
}
1 —— 雲服務器超全購買流程 (新手必備!)
2 —— 阿里ECS雲服務器自定義配置 - 購買教程(新手必備!)
3—— Windows 服務器配置、運行、建站一條龍 !
4 —— Linux 服務器配置、運行、建站一條龍 !

技術交流群:806091680 ! Chinar 歡迎你的加入
本博客為非營利性個人原創,除部分有明確署名的作品外,所刊登的所有作品的著作權均為本人所擁有,本人保留所有法定權利。違者必究
對於需要復制、轉載、鏈接和傳播博客文章或內容的,請及時和本博主進行聯系,留言,Email: ichinar@icloud.com
對於經本博主明確授權和許可使用文章及內容的,使用時請注明文章或內容出處並注明網址>