Unity3D开发飞盘射击案例之界面逻辑(十九)

本节要点

1.开始界面逻辑

1.手臂不能移动

在控制手臂的脚本中,设置一个 bool 状态值;

然后通过游戏管理器进行状态值的切换控制。



2.飞盘不能生成

其实思路和武器控制是一样的;

但是细节稍有不同。


3.开始游戏按钮

需要创建一个“GameStart”脚本;

挂载到开始 UI 上,使用 OnMouseDown()进行处理。

要在这个鼠标按下事件中改变游戏状态。


2.游戏界面逻辑

1.分数累加

①游戏管理器中新建字段存储分数;

②然后定义一个“增加分数”的公开方法;

③然后在武器射击的时候调用这个方法,增加分数;

④控制 UI 显示分数。




2.倒计时

①游戏管理器中新建字段存储时间;

②定义一个标志位,用于开始和停止倒计时;

③定义一个方法,修改标志位;

④在 Update 中实现倒计时;

⑤控制 UI 显示倒计时。




关键代码

Weapon

public class Weapon : MonoBehaviour
{

    //手臂指向鼠标点击的位置
    //声明一个手臂位置的变量;
    private Transform m_transform;


    //利用射线去检测
    //声明一个射线的变量 声明一个存贮射线信息存贮的变量
    private Ray ray;
    private RaycastHit hit;


    //定义一个枪口位置的变量;
    private Transform m_Point;




    //设置特效 线渲染器属性组件 变量

    private LineRenderer m_LineRenderer;



    //设置特效的声音源 射击声
    private AudioSource m_AudioSource;


    //为了不让手臂开始就能控制,设置一个bool类型的开关;
    private  bool canMove = false; //是否控制武器



    //定义一个gamemannger的类型 持用脚本进行控制调用它的脚本 单例模式
    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");


        //特效渲染器组件位置赋值;关键语法  利用枪口的位置设置; 先将查找到的组件 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>
    /// 改变武器可控制的状态
    /// </summary>
    public void ChangeCanMove(bool state) {
        //直接将参数赋值;用来改变bool类型canMove的值;
        canMove = state;
    
    }


    void Update()
    {


        //控制手臂是否可以移动
        if (canMove)
        {





            //使手臂朝向鼠标点击的位置;

            //接收射线的变量  利用摄像机获取射线并赋值;
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);//从屏幕发射到鼠标点击的位置的射线;
            //进行物理检测 

            if (Physics.Raycast(ray, out hit))
            {
                //控制手臂的方向
                //检测成功后调用 游戏对象位置的  朝向 方法 lookat
                m_transform.LookAt(hit.point);//参数是碰撞点


                //检查是否有碰撞;
                //Debug.Log("Collider");
                //场景中没有任何碰撞体 或者打开场景的属性检查;所以手臂不会移动

                //因此 要添加网格碰撞器 选中 游戏物体 add component  加组件 mesh Collider; 
                //但是默认的有4千个顶点,ui设计的只有2千顶点的简模 所以用ui的添加碰撞器



                //成功测试后,发现手的旋转关节不对,就是手是手臂的中心点 可以定义一个父类来控制它 不要以为手臂的中心点来控制
                //建立一个父类,把之前的代码组件移除  设置好父类坐标,将脚本挂载到父类组件去


                //绘制枪口发射线  
                //与绘制射线方法相同 Debug.DrawRay();
                // Debug.DrawLine(m_transform.position,hit.point,Color.red);//参数1: 起始位置 参数2:射线碰撞的位置 参数3:颜色;


                //射线出发的位置不对 所以定义一个空物体存贮枪口的位置 transform
                //怎么查找父类下的组件呢?
                //gameObject.transform.Find("Point");
                //如果游戏对象下面有N个叫Point的组件呢;所以我们只要查找父类下的组件名称即可;
                // m_Point = gameObject.transform.FindChild("Point").GetComponent<Transform>(); // 这是赋值过程,写到Start方法即可;

                //再次绘制射线;
                Debug.DrawLine(m_Point.position, hit.point, Color.red);


                //绘制特效线的位置;注意关键函数 
                m_LineRenderer.SetPosition(0, m_Point.position);//参数1:特效起始位置的下标 参数2:特效起始位置下标的位置 (枪口位置)
                m_LineRenderer.SetPosition(1, hit.point);//参数1:特效结束位置的下标 参数2:特效结束位置下标的位置 (射线碰撞点)



                //射线检测碰撞体后将飞盘击破
                //判断条件 碰撞体的标签并且按下鼠标左键
                //飞盘射击
                if (hit.collider.tag == "FeiPan" && Input.GetMouseButtonDown(0))
                {
                    //如果射击 分数增加
                    m_GameMannger.AddScore();

                    //如果射击到,就播放声音;在Start()中已赋值;
                    m_AudioSource.Play();






                    //通过碰撞到的子组件查找到父类 Transform
                    Transform parent = hit.collider.gameObject.GetComponent<Transform>().parent;//注意组件是单数



                    //通过父类查找到子类下所有的Transform组件;得到的是一个数组

                    Transform[] feiPans = parent.GetComponentsInChildren<Transform>();//注意组件是复数


                    //要实现往下掉落,必须动态添加刚体组件
                    //通过for循环,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 {


    //定义一个游戏对象用来存贮预置体的;
    public GameObject prefab_feiPan;
    

    //定义一个飞盘的Transform组件 用来接收然后吧它设置成父类的组件
    private Transform m_Transform;

    void Start () {

     //协程
    //每隔2秒调用一次 注意关键语句 方法名为字符串 注意括号为英文半角格式;
      //  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() { 
    
       //取消所有协程 有2个重载 怎么看重载 左括号输完再按上下左右键
       CancelInvoke();
    
    }





    /// <summary>
    /// 创建生成飞盘;
    /// </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);


        //发现以上方法生成太慢;一次生成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;
            //将游戏对象下获得Transform组件 设置成父类组件 参数:m_Transform;
            //给生成的飞盘设置成一个服物体;
            go.GetComponent<Transform>().SetParent(m_Transform);
        }
    
    }








    void Update () {
    
    }
}

GameMannger

public class GameMannger : MonoBehaviour {

   /// <summary>
   /// 游戏三种状态
   /// </summary>
    public enum GameState { 
        START,
        GAME,
        END   
    }


    //定义三个游戏对象变量来接收项目中3个游戏UI;
    //存贮3个UI界面的引用;
    private GameObject m_StratUI;
    private GameObject m_GameUI;
    private GameObject m_EndUI;

    //用来显示分数的界面;
    private GUIText m_GUIText_Score;


    //用来显示时间界面;
    private GUIText m_GUIText_time;


    //存贮当前游戏的状态 关键词:GameState;就是枚举的类型 上面定义好的;
    private GameState gameState;



    //背景音乐管理 控制音乐只在游戏进行中播放,其他状态不播放;
    private AudioSource m_BG_AudioSource;


    //武器的脚本 持有武器的脚本才能在游戏管理器里面控制武器的可动性
    private  Weapon  m_Weapon;

    //飞盘脚本 持用飞盘脚本控制生成状态;游戏开始界面和结束界面不生成;
    private FeiPanMannger m_FeiPanMannger;



    //定义一个分数的变量用来存贮分数用的;
    private int score=0;


    //定义一个时间的变量用来计时的;
    private float time = 20;
    //定义一个时间的标志位(开关);
    private bool startTime = false;

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


        //用来显示分数;通过查找持有分数UI的引用;
        m_GUIText_Score = GameObject.Find("GameScore").GetComponent<GUIText>();



        //用来显示时间,通过查找持用时间UI的应用;
        m_GUIText_time = GameObject.Find("GameTime").GetComponent<GUIText>();


        //将背景音乐赋值 通过查找持有背景音乐的引用
       // m_BG_AudioSource = GameObject.Find("ShooterWeapon") as AudioSource; 只能查找组件,不能直查找组件里的内容;
        m_BG_AudioSource=GameObject.Find("Main Camera").GetComponent<AudioSource>();
        
        //只保留游戏开始界面,其他两个界面隐藏;
        //m_GameUI.SetActive(false);
        //m_EndUI.SetActive(false);



        //对武器脚本进行赋值; 一定要在游戏状态改变之前先赋值;
        m_Weapon = GameObject.Find("Weapon").GetComponent<Weapon>();


        //对飞盘脚本进行赋值;
        m_FeiPanMannger=GameObject.Find("FeiPanParent").GetComponent<FeiPanMannger>();

        //传递游戏状态
     ChangeGameState(GameState.START);//开始
     //ChangeGameState(GameState.GAME);//游戏进行中
      // ChangeGameState(GameState.END);//结束;


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

    /// <summary>
    /// 增加分数的方法
    /// </summary>
    public void AddScore() {
        //增加分数
        score++;
        //显示分数;
        m_GUIText_Score.text ="分数:"+ score+"分";
    }

    /// <summary>
    /// 开启倒计时
    /// </summary>
    public void StartTime() {

        startTime = true;
        //在UpDate中修改时间
    }



    
    /// <summary>
    /// 改变游戏的状态
    /// </summary>
    /// <param name="state"> 当前状态</param>
    public void ChangeGameState(GameState state){
    
        //存贮传过来的游戏状态
        gameState=state;

       //开始判断转过来的游戏状态;枚举类型
        if (gameState==GameState.START)     //游戏开始
        {
         
            //游戏开始时 游戏界面可用 其他两个界面隐藏;
            m_StratUI.SetActive(true);
            m_GameUI.SetActive(false);
            m_EndUI.SetActive(false);

            //游戏开始界面不播放

            m_BG_AudioSource.Stop();


            //控制武器脚本里的方法 设置相关的值;
            m_Weapon.ChangeCanMove(false);


             //调用控制飞盘的生成状态脚本的方法;
           // m_FeiPanMannger.StopCreateFeiPan(); 起始不用写,写了也没意义

        }else if (gameState==GameState.GAME)    //游戏进行中
        {
           m_StratUI.SetActive(false);
            m_GameUI.SetActive(true);
            m_EndUI.SetActive(false);

            //游戏进行中播放音乐
            m_BG_AudioSource.Play();

            //控制武器脚本里的方法 设置相关的值;
            m_Weapon.ChangeCanMove(true);

            //调用控制飞盘的生成状态脚本的方法;
            m_FeiPanMannger.StartCreateFeiPan();


            //开始倒计时:调用方法
            StartTime();
            

        }else if (gameState==GameState.END)                 //游戏结束
        {
           m_StratUI.SetActive(false);
            m_GameUI.SetActive(false);
            m_EndUI.SetActive(true);

            //游戏结束状态也不播放
            m_BG_AudioSource.Stop();

            //控制武器脚本里的方法 设置相关的值;
            m_Weapon.ChangeCanMove(false);


            //调用控制飞盘生成状态脚本的方法
            m_FeiPanMannger.StopCreateFeiPan();
        }


    }
    

    void Update () {

        //修改倒计时

        if (startTime)//为真,开始倒计时;
        {
            time -= Time.deltaTime;
            //显示时间
            m_GUIText_time.text = "时间:" + time + "秒";
        }
    
    }
}

GameStart

public class GameStart : MonoBehaviour {


    //按下鼠标后必须改变有的状态 所以必须持有gamemannger的脚本
    private GameMannger m_GameMannger;


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

    }

    /// <summary>
    /// 按下鼠标键游戏开始 脚本是挂在“游戏开始”这个UI上
    /// </summary>
    void OnMouseDown() {

       // Debug.Log("游戏开始");

        //改变游戏的状态;调用这个脚本下的方法的类型的枚举
        m_GameMannger.ChangeGameState(GameMannger.GameState.GAME);//脚本的名称下的枚举类型
    }





    void Update () {
    
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容