Unity3D開發(fā)飛盤射擊案例之界面邏輯及總結(jié)(二十)

本節(jié)要點(diǎn)

1.結(jié)束界面邏輯

1.游戲界面結(jié)束處理

倒計(jì)時(shí)為 0 時(shí),修改游戲狀態(tài),并且將倒計(jì)時(shí)重置;


2.結(jié)束界面顯示總分?jǐn)?shù)

UI 查找,顯示總分?jǐn)?shù)。


3.重新開始按鈕

和開始游戲按鈕處理方式一樣,主要用于修改當(dāng)前的游戲狀態(tài)。


4.細(xì)節(jié)調(diào)整

根據(jù)項(xiàng)目開發(fā)測(cè)試,不斷完善細(xì)節(jié)。


關(guān)鍵代碼

Weapon

public class Weapon : MonoBehaviour
{

    //手臂指向鼠標(biāo)點(diǎn)擊的位置
    //聲明一個(gè)手臂位置的變量;
    private Transform m_transform;


    //利用射線去檢測(cè)
    //聲明一個(gè)射線的變量 聲明一個(gè)存貯射線信息存貯的變量
    private Ray ray;
    private RaycastHit hit;


    //定義一個(gè)槍口位置的變量;
    private Transform m_Point;




    //設(shè)置特效 線渲染器屬性組件 變量

    private LineRenderer m_LineRenderer;



    //設(shè)置特效的聲音源 射擊聲
    private AudioSource m_AudioSource;


    //為了不讓手臂開始就能控制,設(shè)置一個(gè)bool類型的開關(guān);
    private  bool canMove = false; //是否控制武器



    //定義一個(gè)gamemannger的類型 持用腳本進(jìn)行控制調(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>();


        //對(duì)m_GameMannger進(jìn)行賦值;
        m_GameMannger=GameObject.Find("UI").GetComponent<GameMannger>();

    }

    /// <summary>
    /// 改變武器可控制的狀態(tài)
    /// </summary>
    public void ChangeCanMove(bool state) {
        //直接將參數(shù)賦值;用來改變bool類型canMove的值;
        canMove = state;
    
    }


    void Update()
    {


        //控制手臂是否可以移動(dòng)
        if (canMove)
        {





            //使手臂朝向鼠標(biāo)點(diǎn)擊的位置;

            //接收射線的變量  利用攝像機(jī)獲取射線并賦值;
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);//從屏幕發(fā)射到鼠標(biāo)點(diǎn)擊的位置的射線;
            //進(jìn)行物理檢測(cè) 

            if (Physics.Raycast(ray, out hit))
            {
                //控制手臂的方向
                //檢測(cè)成功后調(diào)用 游戲?qū)ο笪恢玫? 朝向 方法 lookat
                m_transform.LookAt(hit.point);//參數(shù)是碰撞點(diǎn)


                //檢查是否有碰撞;
                //Debug.Log("Collider");
                //場(chǎng)景中沒有任何碰撞體 或者打開場(chǎng)景的屬性檢查;所以手臂不會(huì)移動(dòng)

                //因此 要添加網(wǎng)格碰撞器 選中 游戲物體 add component  加組件 mesh Collider; 
                //但是默認(rèn)的有4千個(gè)頂點(diǎn),ui設(shè)計(jì)的只有2千頂點(diǎn)的簡(jiǎn)模 所以用ui的添加碰撞器



                //成功測(cè)試后,發(fā)現(xiàn)手的旋轉(zhuǎn)關(guān)節(jié)不對(duì),就是手是手臂的中心點(diǎn) 可以定義一個(gè)父類來控制它 不要以為手臂的中心點(diǎn)來控制
                //建立一個(gè)父類,把之前的代碼組件移除  設(shè)置好父類坐標(biāo),將腳本掛載到父類組件去


                //繪制槍口發(fā)射線  
                //與繪制射線方法相同 Debug.DrawRay();
                // Debug.DrawLine(m_transform.position,hit.point,Color.red);//參數(shù)1: 起始位置 參數(shù)2:射線碰撞的位置 參數(shù)3:顏色;


                //射線出發(fā)的位置不對(duì) 所以定義一個(gè)空物體存貯槍口的位置 transform
                //怎么查找父類下的組件呢?
                //gameObject.transform.Find("Point");
                //如果游戲?qū)ο笙旅嬗蠳個(gè)叫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:特效起始位置的下標(biāo) 參數(shù)2:特效起始位置下標(biāo)的位置 (槍口位置)
                m_LineRenderer.SetPosition(1, hit.point);//參數(shù)1:特效結(jié)束位置的下標(biāo) 參數(shù)2:特效結(jié)束位置下標(biāo)的位置 (射線碰撞點(diǎn))



                //射線檢測(cè)碰撞體后將飛盤擊破
                //判斷條件 碰撞體的標(biāo)簽并且按下鼠標(biāo)左鍵
                //飛盤射擊
                if (hit.collider.tag == "FeiPan" && Input.GetMouseButtonDown(0))
                {
                    //如果射擊 分?jǐn)?shù)增加
                    m_GameMannger.AddScore();

                    //如果射擊到,就播放聲音;在Start()中已賦值;
                    m_AudioSource.Play();






                    //通過碰撞到的子組件查找到父類 Transform
                    Transform parent = hit.collider.gameObject.GetComponent<Transform>().parent;//注意組件是單數(shù)



                    //通過父類查找到子類下所有的Transform組件;得到的是一個(gè)數(shù)組

                    Transform[] feiPans = parent.GetComponentsInChildren<Transform>();//注意組件是復(fù)數(shù)


                    //要實(shí)現(xiàn)往下掉落,必須動(dòng)態(tài)添加剛體組件
                    //通過for循環(huán),Transform點(diǎn)出來符物體,然后添加剛體組件
                    for (int i = 0; i < feiPans.Length; i++)
                    {
                        //通過子物體組件尋找出父類添加剛體組件;模擬掉落效果;不用接收賦值;
                        feiPans[i].gameObject.AddComponent<Rigidbody>();


                    }


                    //18個(gè)組件掉落后一直掉落并沒有銷毀,必須把父物體銷毀
                    //2秒后,銷毀父物體 通過transform 點(diǎn)出來 父物體組件 銷毀的gameobject
                    GameObject.Destroy(parent.gameObject, 2.0f);


                }


            }



        }
    }
}

FeiPanMannger

public class FeiPanMannger : MonoBehaviour {


    //定義一個(gè)游戲?qū)ο笥脕泶尜A預(yù)置體的;
    public GameObject prefab_feiPan;
    

    //定義一個(gè)飛盤的Transform組件 用來接收然后吧它設(shè)置成父類的組件
    private Transform m_Transform;

    void Start () {

     //協(xié)程
    //每隔2秒調(diào)用一次 注意關(guān)鍵語句 方法名為字符串 注意括號(hào)為英文半角格式;
      //  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個(gè)重載 怎么看重載 左括號(hào)輸完再按上下左右鍵
       CancelInvoke();
    
    }

    /// <summary>
    /// 當(dāng)游戲結(jié)束時(shí),調(diào)此方法,移除所有飛盤
    /// </summary>
   public void RemoveFeiPan() {

       Transform[] fp = m_Transform.GetComponentsInChildren<Transform>();//數(shù)組形式 組件是復(fù)數(shù) s
       //下標(biāo)必須從1開始,否則會(huì)連父類也被銷毀;
       for (int i = 1; i < fp.Length; i++)
       {
           GameObject.Destroy(fp[i].gameObject);//銷毀 transform 的游戲?qū)ο螅?       }

   
   }






    /// <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));

        ////實(shí)例化生成飛盤 
        //GameObject.Instantiate(prefab_feiPan,pos,Quaternion.identity);


        //發(fā)現(xiàn)以上方法生成太慢;一次生成3個(gè);

        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);
            //將實(shí)例化的飛盤存貯起來
            GameObject go = GameObject.Instantiate(prefab_feiPan, pos, Quaternion.identity) as GameObject;
            //將游戲?qū)ο笙芦@得Transform組件 設(shè)置成父類組件 參數(shù):m_Transform;
            //給生成的飛盤設(shè)置成一個(gè)服物體;
            go.GetComponent<Transform>().SetParent(m_Transform);
        }
    
    }








    void Update () {
    
    }
}

GameMannger

public class GameMannger : MonoBehaviour
{

    /// <summary>
    /// 游戲三種狀態(tài)
    /// </summary>
    public enum GameState
    {
        START,
        GAME,
        END
    }


    //定義三個(gè)游戲?qū)ο笞兞縼斫邮枕?xiàng)目中3個(gè)游戲UI;
    //存貯3個(gè)UI界面的引用;
    private GameObject m_StratUI;
    private GameObject m_GameUI;
    private GameObject m_EndUI;

    //用來顯示分?jǐn)?shù)的界面;
    private GUIText m_GUIText_Score;
    //用來顯示時(shí)間界面;
    private GUIText m_GUIText_time;
    //用來顯示總分?jǐn)?shù)界面;
    private GUIText m_GUIText_TotalScore;


    //存貯當(dāng)前游戲的狀態(tài) 關(guān)鍵詞:GameState;就是枚舉的類型 上面定義好的;
    private GameState gameState;



    //背景音樂管理 控制音樂只在游戲進(jìn)行中播放,其他狀態(tài)不播放;
    private AudioSource m_BG_AudioSource;


    //武器的腳本 持有武器的腳本才能在游戲管理器里面控制武器的可動(dòng)性
    private Weapon m_Weapon;

    //飛盤腳本 持用飛盤腳本控制生成狀態(tài);游戲開始界面和結(jié)束界面不生成;
    private FeiPanMannger m_FeiPanMannger;



    //定義一個(gè)分?jǐn)?shù)的變量用來存貯分?jǐn)?shù)用的;
    private int score = 0;


    //定義一個(gè)時(shí)間的變量用來計(jì)時(shí)的;
    private float time = 20;
    //定義一個(gè)時(shí)間的標(biāo)志位(開關(guān));
    private bool startTime = false;

    void Start()
    {
        //賦值過程 通過Find方法去查找并賦值;
        //通過查找持有三個(gè)UI的引用
        m_StratUI = GameObject.Find("StratUI");
        m_GameUI = GameObject.Find("GameUI");
        m_EndUI = GameObject.Find("EndUI");


        //用來顯示分?jǐn)?shù);通過查找持有分?jǐn)?shù)UI的引用;
        m_GUIText_Score = GameObject.Find("GameScore").GetComponent<GUIText>();
        //用來顯示時(shí)間,通過查找持用時(shí)間UI的應(yīng)用;
        m_GUIText_time = GameObject.Find("GameTime").GetComponent<GUIText>();
        //用來顯示總分?jǐn)?shù);通過查找持有總分?jǐn)?shù)UI的引用;
        m_GUIText_TotalScore = GameObject.Find("GameTotalScore ").GetComponent<GUIText>();


        //將背景音樂賦值 通過查找持有背景音樂的引用
        // m_BG_AudioSource = GameObject.Find("ShooterWeapon") as AudioSource; 只能查找組件,不能直查找組件里的內(nèi)容;
        m_BG_AudioSource = GameObject.Find("Main Camera").GetComponent<AudioSource>();

        //只保留游戲開始界面,其他兩個(gè)界面隱藏;
        //m_GameUI.SetActive(false);
        //m_EndUI.SetActive(false);



        //對(duì)武器腳本進(jìn)行賦值; 一定要在游戲狀態(tài)改變之前先賦值;
        m_Weapon = GameObject.Find("Weapon").GetComponent<Weapon>();


        //對(duì)飛盤腳本進(jìn)行賦值;
        m_FeiPanMannger = GameObject.Find("FeiPanParent").GetComponent<FeiPanMannger>();

        //傳遞游戲狀態(tài)
        ChangeGameState(GameState.START);//開始
        //ChangeGameState(GameState.GAME);//游戲進(jìn)行中
        // ChangeGameState(GameState.END);//結(jié)束;




        //score=GameObject.Find("UI").GetComponent<>();
    }

    /// <summary>
    /// 增加分?jǐn)?shù)的方法
    /// </summary>
    public void AddScore()
    {
        //增加分?jǐn)?shù)
        score++;
        //顯示分?jǐn)?shù);
        m_GUIText_Score.text = "分?jǐn)?shù):" + score + "分";
    }

    /// <summary>
    /// 開啟倒計(jì)時(shí)
    /// </summary>
    public void StartTime()
    {

        startTime = true;
        //在UpDate中修改時(shí)間
    }




    /// <summary>
    /// 改變游戲的狀態(tài)
    /// </summary>
    /// <param name="state"> 當(dāng)前狀態(tài)</param>
    public void ChangeGameState(GameState state)
    {

        //存貯傳過來的游戲狀態(tài)
        gameState = state;

        //開始判斷轉(zhuǎn)過來的游戲狀態(tài);枚舉類型
        if (gameState == GameState.START)     //游戲開始
        {

            //游戲開始時(shí) 游戲界面可用 其他兩個(gè)界面隱藏;
            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)    //游戲進(jìn)行中
        {
            m_StratUI.SetActive(false);
            m_GameUI.SetActive(true);
            m_EndUI.SetActive(false);

            //游戲進(jìn)行中播放音樂
            m_BG_AudioSource.Play();

            //控制武器腳本里的方法 設(shè)置相關(guān)的值;
            m_Weapon.ChangeCanMove(true);

            //調(diào)用控制飛盤的生成狀態(tài)腳本的方法;
            m_FeiPanMannger.StartCreateFeiPan();


            //開始倒計(jì)時(shí):調(diào)用方法
            StartTime();

            //同步UI 但游戲重新開始時(shí),將顯示分?jǐn)?shù)為零
            m_GUIText_Score.text = "分?jǐn)?shù):" +score +"分";


        }
        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();

            //游戲結(jié)束時(shí),銷毀所有飛盤;上面已經(jīng)有定義個(gè)管理飛盤的腳本,直接調(diào)用即可;
            m_FeiPanMannger.RemoveFeiPan();
        }


    }


    void Update()
    {

        //修改倒計(jì)時(shí)

        if (startTime)//為真,開始倒計(jì)時(shí);
        {
            time -= Time.deltaTime;
            //顯示時(shí)間
            m_GUIText_time.text = "時(shí)間:" + time + "秒";

            //如果時(shí)間小于等于0,讓UI文本顯示時(shí)間為零 并且改變游戲的狀態(tài);
            if (time <= 0)
            {
                m_GUIText_time.text = "時(shí)間:0 秒";
                ChangeGameState(GameState.END);
                //顯示總分?jǐn)?shù)
                m_GUIText_TotalScore.text = "總分:" + score + "分";

                //重置時(shí)間和標(biāo)志位及分?jǐn)?shù);
                time = 20;
                startTime = false;
                score = 0;

             
                

            }
        }

    }
}

GameStart

public class GameStart : MonoBehaviour {


    //按下鼠標(biāo)后必須改變有的狀態(tài) 所以必須持有g(shù)amemannger的腳本
    private GameMannger m_GameMannger;


    void Start () {
    
        //賦值
        m_GameMannger=GameObject.Find("UI").GetComponent<GameMannger>();

    }

    /// <summary>
    /// 按下鼠標(biāo)鍵游戲開始 腳本是掛在“游戲開始”這個(gè)UI上
    /// </summary>
    void OnMouseDown() {

       // Debug.Log("游戲開始");

        //改變游戲的狀態(tài);調(diào)用這個(gè)腳本下的方法的類型的枚舉
        m_GameMannger.ChangeGameState(GameMannger.GameState.GAME);//腳本的名稱下的枚舉類型
    }





    void Update () {
    
    }
}

GameReset

public class GameReset : MonoBehaviour {

    //c重新開始的UI
    //定義一個(gè)游戲管理腳本的變量
    private GameMannger m_GameMannger;

    void Start () {
    
        //對(duì)變量進(jìn)行賦值;通過查找賦值;
        m_GameMannger=GameObject.Find("UI").GetComponent<GameMannger>();


    }
    

    //寫個(gè)鼠標(biāo)按下事件,重置游戲(改變游戲的剛開始的狀態(tài)) 調(diào)用方法;
    void OnMouseDown() {

        //為什么沒執(zhí)行呢?測(cè)試下
        //Debug.Log("888");
        //上面有執(zhí)行,為什么沒執(zhí)行下面這一句呢?
       // m_GameMannger.ChangeGameState(GameMannger.GameState.START);//注意參數(shù)的格式;
        //因?yàn)樵赨pdate中,時(shí)間小于0或者starttime是ture時(shí),調(diào)轉(zhuǎn)到結(jié)束界面; 所以在Gamemannger下Update中重置下時(shí)間相關(guān)數(shù)據(jù)并且把標(biāo)志位改成false;
        m_GameMannger.ChangeGameState(GameMannger.GameState.START);//注意參數(shù)的格式;
    
    }




    void Update () {
    
    }
}

小結(jié)

Unity API.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容