本節(jié)要點
1.開始界面邏輯
1.手臂不能移動
在控制手臂的腳本中,設(shè)置一個 bool 狀態(tài)值纤壁;
然后通過游戲管理器進行狀態(tài)值的切換控制吹缔。
2.飛盤不能生成
其實思路和武器控制是一樣的;
但是細節(jié)稍有不同炫加。
3.開始游戲按鈕
需要創(chuàng)建一個“GameStart”腳本;
掛載到開始 UI 上铺然,使用 OnMouseDown()進行處理俗孝。
要在這個鼠標按下事件中改變游戲狀態(tài)。
2.游戲界面邏輯
1.分數(shù)累加
①游戲管理器中新建字段存儲分數(shù)魄健;
②然后定義一個“增加分數(shù)”的公開方法赋铝;
③然后在武器射擊的時候調(diào)用這個方法,增加分數(shù)沽瘦;
④控制 UI 顯示分數(shù)革骨。
2.倒計時
①游戲管理器中新建字段存儲時間;
②定義一個標志位析恋,用于開始和停止倒計時良哲;
③定義一個方法,修改標志位助隧;
④在 Update 中實現(xiàn)倒計時筑凫;
⑤控制 UI 顯示倒計時。
關(guān)鍵代碼
Weapon
public class Weapon : MonoBehaviour
{
//手臂指向鼠標點擊的位置
//聲明一個手臂位置的變量并村;
private Transform m_transform;
//利用射線去檢測
//聲明一個射線的變量 聲明一個存貯射線信息存貯的變量
private Ray ray;
private RaycastHit hit;
//定義一個槍口位置的變量巍实;
private Transform m_Point;
//設(shè)置特效 線渲染器屬性組件 變量
private LineRenderer m_LineRenderer;
//設(shè)置特效的聲音源 射擊聲
private AudioSource m_AudioSource;
//為了不讓手臂開始就能控制,設(shè)置一個bool類型的開關(guān)哩牍;
private bool canMove = false; //是否控制武器
//定義一個gamemannger的類型 持用腳本進行控制調(diào)用它的腳本 單例模式
private GameMannger m_GameMannger;
void Start()
{
//將Transform 位置賦值
m_transform = gameObject.GetComponent<Transform>();
//槍口位置賦值棚潦;
// m_Point = gameObject.transform.FindChild("Point").GetComponent<Transform>();
m_Point = m_transform.FindChild("Point");
//特效渲染器組件位置賦值;關(guān)鍵語法 利用槍口的位置設(shè)置膝昆; 先將查找到的組件 linerenderer 存貯起來
m_LineRenderer = m_Point.gameObject.GetComponent<LineRenderer>();
//將聲音源賦值丸边;通過查找武器父類獲得下面的射擊聲音源叠必; 不要勾選paly on awake 和loop;
m_AudioSource = gameObject.GetComponent<AudioSource>();
//對m_GameMannger進行賦值妹窖;
m_GameMannger=GameObject.Find("UI").GetComponent<GameMannger>();
}
/// <summary>
/// 改變武器可控制的狀態(tài)
/// </summary>
public void ChangeCanMove(bool state) {
//直接將參數(shù)賦值纬朝;用來改變bool類型canMove的值;
canMove = state;
}
void Update()
{
//控制手臂是否可以移動
if (canMove)
{
//使手臂朝向鼠標點擊的位置嘱吗;
//接收射線的變量 利用攝像機獲取射線并賦值玄组;
ray = Camera.main.ScreenPointToRay(Input.mousePosition);//從屏幕發(fā)射到鼠標點擊的位置的射線;
//進行物理檢測
if (Physics.Raycast(ray, out hit))
{
//控制手臂的方向
//檢測成功后調(diào)用 游戲?qū)ο笪恢玫? 朝向 方法 lookat
m_transform.LookAt(hit.point);//參數(shù)是碰撞點
//檢查是否有碰撞谒麦;
//Debug.Log("Collider");
//場景中沒有任何碰撞體 或者打開場景的屬性檢查俄讹;所以手臂不會移動
//因此 要添加網(wǎng)格碰撞器 選中 游戲物體 add component 加組件 mesh Collider;
//但是默認的有4千個頂點绕德,ui設(shè)計的只有2千頂點的簡模 所以用ui的添加碰撞器
//成功測試后患膛,發(fā)現(xiàn)手的旋轉(zhuǎn)關(guān)節(jié)不對,就是手是手臂的中心點 可以定義一個父類來控制它 不要以為手臂的中心點來控制
//建立一個父類耻蛇,把之前的代碼組件移除 設(shè)置好父類坐標踪蹬,將腳本掛載到父類組件去
//繪制槍口發(fā)射線
//與繪制射線方法相同 Debug.DrawRay();
// Debug.DrawLine(m_transform.position,hit.point,Color.red);//參數(shù)1: 起始位置 參數(shù)2:射線碰撞的位置 參數(shù)3:顏色;
//射線出發(fā)的位置不對 所以定義一個空物體存貯槍口的位置 transform
//怎么查找父類下的組件呢臣咖?
//gameObject.transform.Find("Point");
//如果游戲?qū)ο笙旅嬗蠳個叫Point的組件呢跃捣;所以我們只要查找父類下的組件名稱即可;
// m_Point = gameObject.transform.FindChild("Point").GetComponent<Transform>(); // 這是賦值過程夺蛇,寫到Start方法即可疚漆;
//再次繪制射線;
Debug.DrawLine(m_Point.position, hit.point, Color.red);
//繪制特效線的位置刁赦;注意關(guān)鍵函數(shù)
m_LineRenderer.SetPosition(0, m_Point.position);//參數(shù)1:特效起始位置的下標 參數(shù)2:特效起始位置下標的位置 (槍口位置)
m_LineRenderer.SetPosition(1, hit.point);//參數(shù)1:特效結(jié)束位置的下標 參數(shù)2:特效結(jié)束位置下標的位置 (射線碰撞點)
//射線檢測碰撞體后將飛盤擊破
//判斷條件 碰撞體的標簽并且按下鼠標左鍵
//飛盤射擊
if (hit.collider.tag == "FeiPan" && Input.GetMouseButtonDown(0))
{
//如果射擊 分數(shù)增加
m_GameMannger.AddScore();
//如果射擊到娶聘,就播放聲音;在Start()中已賦值甚脉;
m_AudioSource.Play();
//通過碰撞到的子組件查找到父類 Transform
Transform parent = hit.collider.gameObject.GetComponent<Transform>().parent;//注意組件是單數(shù)
//通過父類查找到子類下所有的Transform組件丸升;得到的是一個數(shù)組
Transform[] feiPans = parent.GetComponentsInChildren<Transform>();//注意組件是復(fù)數(shù)
//要實現(xiàn)往下掉落,必須動態(tài)添加剛體組件
//通過for循環(huán)牺氨,Transform點出來符物體狡耻,然后添加剛體組件
for (int i = 0; i < feiPans.Length; i++)
{
//通過子物體組件尋找出父類添加剛體組件;模擬掉落效果波闹;不用接收賦值酝豪;
feiPans[i].gameObject.AddComponent<Rigidbody>();
}
//18個組件掉落后一直掉落并沒有銷毀,必須把父物體銷毀
//2秒后精堕,銷毀父物體 通過transform 點出來 父物體組件 銷毀的gameobject
GameObject.Destroy(parent.gameObject, 2.0f);
}
}
}
}
}
FeiPanMannger
public class FeiPanMannger : MonoBehaviour {
//定義一個游戲?qū)ο笥脕泶尜A預(yù)置體的;
public GameObject prefab_feiPan;
//定義一個飛盤的Transform組件 用來接收然后吧它設(shè)置成父類的組件
private Transform m_Transform;
void Start () {
//協(xié)程
//每隔2秒調(diào)用一次 注意關(guān)鍵語句 方法名為字符串 注意括號為英文半角格式蒲障;
// InvokeRepeating("CreateFeiPan",2.0f,2.0f);
//飛盤不能抑制生成歹篓,不符合游戲邏輯 封裝方法瘫证;
//將m_Transform組件賦值;
m_Transform=gameObject.GetComponent<Transform>();
}
/// <summary>
/// 開始生成飛盤
/// </summary>
public void StartCreateFeiPan() {
InvokeRepeating("CreateFeiPan",0.5f,2.0f);
}
/// <summary>
/// 停止生成飛盤
/// </summary>
public void StopCreateFeiPan() {
//取消所有協(xié)程 有2個重載 怎么看重載 左括號輸完再按上下左右鍵
CancelInvoke();
}
/// <summary>
/// 創(chuàng)建生成飛盤庄撮;
/// </summary>
void CreateFeiPan() {
//先獲取飛盤的位置背捌;
//Vector3 pos = new Vector3(Random.Range(-4.0f,4.0f),Random.Range(0.5f,1.5f),Random.Range(4.0f,13.0f));
////實例化生成飛盤
//GameObject.Instantiate(prefab_feiPan,pos,Quaternion.identity);
//發(fā)現(xiàn)以上方法生成太慢;一次生成3個洞斯;
for (int i = 0; i < 3; i++)
{
Vector3 pos = new Vector3(Random.Range(-4.0f,4.0f),Random.Range(1.0f,3.5f),Random.Range(-1.0f,13.0f));
//GameObject.Instantiate(prefab_feiPan,pos,Quaternion.identity);
//將實例化的飛盤存貯起來
GameObject go = GameObject.Instantiate(prefab_feiPan, pos, Quaternion.identity) as GameObject;
//將游戲?qū)ο笙芦@得Transform組件 設(shè)置成父類組件 參數(shù):m_Transform;
//給生成的飛盤設(shè)置成一個服物體毡庆;
go.GetComponent<Transform>().SetParent(m_Transform);
}
}
void Update () {
}
}
GameMannger
public class GameMannger : MonoBehaviour {
/// <summary>
/// 游戲三種狀態(tài)
/// </summary>
public enum GameState {
START,
GAME,
END
}
//定義三個游戲?qū)ο笞兞縼斫邮枕椖恐?個游戲UI;
//存貯3個UI界面的引用烙如;
private GameObject m_StratUI;
private GameObject m_GameUI;
private GameObject m_EndUI;
//用來顯示分數(shù)的界面么抗;
private GUIText m_GUIText_Score;
//用來顯示時間界面;
private GUIText m_GUIText_time;
//存貯當前游戲的狀態(tài) 關(guān)鍵詞:GameState亚铁;就是枚舉的類型 上面定義好的蝇刀;
private GameState gameState;
//背景音樂管理 控制音樂只在游戲進行中播放,其他狀態(tài)不播放徘溢;
private AudioSource m_BG_AudioSource;
//武器的腳本 持有武器的腳本才能在游戲管理器里面控制武器的可動性
private Weapon m_Weapon;
//飛盤腳本 持用飛盤腳本控制生成狀態(tài)吞琐;游戲開始界面和結(jié)束界面不生成;
private FeiPanMannger m_FeiPanMannger;
//定義一個分數(shù)的變量用來存貯分數(shù)用的然爆;
private int score=0;
//定義一個時間的變量用來計時的站粟;
private float time = 20;
//定義一個時間的標志位(開關(guān));
private bool startTime = false;
void Start () {
//賦值過程 通過Find方法去查找并賦值曾雕;
//通過查找持有三個UI的引用
m_StratUI = GameObject.Find("StratUI");
m_GameUI = GameObject.Find("GameUI");
m_EndUI = GameObject.Find("EndUI");
//用來顯示分數(shù)奴烙;通過查找持有分數(shù)UI的引用;
m_GUIText_Score = GameObject.Find("GameScore").GetComponent<GUIText>();
//用來顯示時間翻默,通過查找持用時間UI的應(yīng)用缸沃;
m_GUIText_time = GameObject.Find("GameTime").GetComponent<GUIText>();
//將背景音樂賦值 通過查找持有背景音樂的引用
// m_BG_AudioSource = GameObject.Find("ShooterWeapon") as AudioSource; 只能查找組件,不能直查找組件里的內(nèi)容修械;
m_BG_AudioSource=GameObject.Find("Main Camera").GetComponent<AudioSource>();
//只保留游戲開始界面趾牧,其他兩個界面隱藏;
//m_GameUI.SetActive(false);
//m_EndUI.SetActive(false);
//對武器腳本進行賦值肯污; 一定要在游戲狀態(tài)改變之前先賦值翘单;
m_Weapon = GameObject.Find("Weapon").GetComponent<Weapon>();
//對飛盤腳本進行賦值;
m_FeiPanMannger=GameObject.Find("FeiPanParent").GetComponent<FeiPanMannger>();
//傳遞游戲狀態(tài)
ChangeGameState(GameState.START);//開始
//ChangeGameState(GameState.GAME);//游戲進行中
// ChangeGameState(GameState.END);//結(jié)束蹦渣;
//score=GameObject.Find("UI").GetComponent<>();
}
/// <summary>
/// 增加分數(shù)的方法
/// </summary>
public void AddScore() {
//增加分數(shù)
score++;
//顯示分數(shù)哄芜;
m_GUIText_Score.text ="分數(shù):"+ score+"分";
}
/// <summary>
/// 開啟倒計時
/// </summary>
public void StartTime() {
startTime = true;
//在UpDate中修改時間
}
/// <summary>
/// 改變游戲的狀態(tài)
/// </summary>
/// <param name="state"> 當前狀態(tài)</param>
public void ChangeGameState(GameState state){
//存貯傳過來的游戲狀態(tài)
gameState=state;
//開始判斷轉(zhuǎn)過來的游戲狀態(tài);枚舉類型
if (gameState==GameState.START) //游戲開始
{
//游戲開始時 游戲界面可用 其他兩個界面隱藏柬唯;
m_StratUI.SetActive(true);
m_GameUI.SetActive(false);
m_EndUI.SetActive(false);
//游戲開始界面不播放
m_BG_AudioSource.Stop();
//控制武器腳本里的方法 設(shè)置相關(guān)的值认臊;
m_Weapon.ChangeCanMove(false);
//調(diào)用控制飛盤的生成狀態(tài)腳本的方法;
// m_FeiPanMannger.StopCreateFeiPan(); 起始不用寫锄奢,寫了也沒意義
}else if (gameState==GameState.GAME) //游戲進行中
{
m_StratUI.SetActive(false);
m_GameUI.SetActive(true);
m_EndUI.SetActive(false);
//游戲進行中播放音樂
m_BG_AudioSource.Play();
//控制武器腳本里的方法 設(shè)置相關(guān)的值失晴;
m_Weapon.ChangeCanMove(true);
//調(diào)用控制飛盤的生成狀態(tài)腳本的方法剧腻;
m_FeiPanMannger.StartCreateFeiPan();
//開始倒計時:調(diào)用方法
StartTime();
}else if (gameState==GameState.END) //游戲結(jié)束
{
m_StratUI.SetActive(false);
m_GameUI.SetActive(false);
m_EndUI.SetActive(true);
//游戲結(jié)束狀態(tài)也不播放
m_BG_AudioSource.Stop();
//控制武器腳本里的方法 設(shè)置相關(guān)的值;
m_Weapon.ChangeCanMove(false);
//調(diào)用控制飛盤生成狀態(tài)腳本的方法
m_FeiPanMannger.StopCreateFeiPan();
}
}
void Update () {
//修改倒計時
if (startTime)//為真涂屁,開始倒計時书在;
{
time -= Time.deltaTime;
//顯示時間
m_GUIText_time.text = "時間:" + time + "秒";
}
}
}
GameStart
public class GameStart : MonoBehaviour {
//按下鼠標后必須改變有的狀態(tài) 所以必須持有g(shù)amemannger的腳本
private GameMannger m_GameMannger;
void Start () {
//賦值
m_GameMannger=GameObject.Find("UI").GetComponent<GameMannger>();
}
/// <summary>
/// 按下鼠標鍵游戲開始 腳本是掛在“游戲開始”這個UI上
/// </summary>
void OnMouseDown() {
// Debug.Log("游戲開始");
//改變游戲的狀態(tài);調(diào)用這個腳本下的方法的類型的枚舉
m_GameMannger.ChangeGameState(GameMannger.GameState.GAME);//腳本的名稱下的枚舉類型
}
void Update () {
}
}