美文网首页
Unity3D开发飞盘射击案例之界面逻辑及总结(二十)

Unity3D开发飞盘射击案例之界面逻辑及总结(二十)

作者: TonyWan_AR | 来源:发表于2016-12-16 20:48 被阅读142次

    本节要点

    1.结束界面逻辑
    
    1.游戏界面结束处理
    
    倒计时为 0 时,修改游戏状态,并且将倒计时重置;
    
    
    2.结束界面显示总分数
    
    UI 查找,显示总分数。
    
    
    3.重新开始按钮
    
    和开始游戏按钮处理方式一样,主要用于修改当前的游戏状态。
    
    
    4.细节调整
    
    根据项目开发测试,不断完善细节。
    
    
    

    关键代码

    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>
       public void RemoveFeiPan() {
    
           Transform[] fp = m_Transform.GetComponentsInChildren<Transform>();//数组形式 组件是复数 s
           //下标必须从1开始,否则会连父类也被销毁;
           for (int i = 1; i < fp.Length; i++)
           {
               GameObject.Destroy(fp[i].gameObject);//销毁 transform 的游戏对象;
           }
    
       
       }
    
    
    
    
    
    
        /// <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;
        //用来显示总分数界面;
        private GUIText m_GUIText_TotalScore;
    
    
        //存贮当前游戏的状态 关键词: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>();
            //用来显示总分数;通过查找持有总分数UI的引用;
            m_GUIText_TotalScore = GameObject.Find("GameTotalScore ").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();
    
                //同步UI 但游戏重新开始时,将显示分数为零
                m_GUIText_Score.text = "分数:" +score +"分";
    
    
            }
            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();
    
                //游戏结束时,销毁所有飞盘;上面已经有定义个管理飞盘的脚本,直接调用即可;
                m_FeiPanMannger.RemoveFeiPan();
            }
    
    
        }
    
    
        void Update()
        {
    
            //修改倒计时
    
            if (startTime)//为真,开始倒计时;
            {
                time -= Time.deltaTime;
                //显示时间
                m_GUIText_time.text = "时间:" + time + "秒";
    
                //如果时间小于等于0,让UI文本显示时间为零 并且改变游戏的状态;
                if (time <= 0)
                {
                    m_GUIText_time.text = "时间:0 秒";
                    ChangeGameState(GameState.END);
                    //显示总分数
                    m_GUIText_TotalScore.text = "总分:" + score + "分";
    
                    //重置时间和标志位及分数;
                    time = 20;
                    startTime = false;
                    score = 0;
    
                 
                    
    
                }
            }
    
        }
    }
    
    

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

    GameReset

    public class GameReset : MonoBehaviour {
    
        //c重新开始的UI
        //定义一个游戏管理脚本的变量
        private GameMannger m_GameMannger;
    
        void Start () {
        
            //对变量进行赋值;通过查找赋值;
            m_GameMannger=GameObject.Find("UI").GetComponent<GameMannger>();
    
    
        }
        
    
        //写个鼠标按下事件,重置游戏(改变游戏的刚开始的状态) 调用方法;
        void OnMouseDown() {
    
            //为什么没执行呢?测试下
            //Debug.Log("888");
            //上面有执行,为什么没执行下面这一句呢?
           // m_GameMannger.ChangeGameState(GameMannger.GameState.START);//注意参数的格式;
            //因为在Update中,时间小于0或者starttime是ture时,调转到结束界面; 所以在Gamemannger下Update中重置下时间相关数据并且把标志位改成false;
            m_GameMannger.ChangeGameState(GameMannger.GameState.START);//注意参数的格式;
        
        }
    
    
    
    
        void Update () {
        
        }
    }
    
    

    小结

    Unity API.png

    相关文章

      网友评论

          本文标题:Unity3D开发飞盘射击案例之界面逻辑及总结(二十)

          本文链接:https://www.haomeiwen.com/subject/bftomttx.html