Unity3D開發(fā)飛盤射擊案例之界面邏輯(十九)

本節(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 () {
    
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拆又,一起剝皮案震驚了整個濱河市儒旬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌帖族,老刑警劉巖栈源,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異盟萨,居然都是意外死亡凉翻,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門捻激,熙熙樓的掌柜王于貴愁眉苦臉地迎上來制轰,“玉大人,你說我怎么就攤上這事胞谭±龋” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵丈屹,是天一觀的道長调俘。 經(jīng)常有香客問我,道長旺垒,這世上最難降的妖魔是什么彩库? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮先蒋,結(jié)果婚禮上骇钦,老公的妹妹穿的比我還像新娘。我一直安慰自己竞漾,他們只是感情好眯搭,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著业岁,像睡著了一般鳞仙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上笔时,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天棍好,我揣著相機與錄音,去河邊找鬼。 笑死梳玫,一個胖子當著我的面吹牛爹梁,可吹牛的內(nèi)容都是我干的右犹。 我是一名探鬼主播提澎,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼念链!你這毒婦竟也來了盼忌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤掂墓,失蹤者是張志新(化名)和其女友劉穎谦纱,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體君编,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡跨嘉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吃嘿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祠乃。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖兑燥,靈堂內(nèi)的尸體忽然破棺而出亮瓷,到底是詐尸還是另有隱情,我是刑警寧澤降瞳,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布嘱支,位于F島的核電站,受9級特大地震影響挣饥,放射性物質(zhì)發(fā)生泄漏除师。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一扔枫、第九天 我趴在偏房一處隱蔽的房頂上張望汛聚。 院中可真熱鬧,春花似錦茧吊、人聲如沸贞岭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞄桨。三九已至,卻和暖如春讶踪,著一層夾襖步出監(jiān)牢的瞬間芯侥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留柱查,地道東北人廓俭。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像唉工,于是被迫代替她去往敵國和親研乒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容