美文网首页
《飞盘射击》案例总结

《飞盘射击》案例总结

作者: 街头顽禽 | 来源:发表于2018-01-30 00:39 被阅读46次

    《飞盘射击》案例总结

    第一部分:Unity组件

    什么是UI?

    UI就是用户操作界面

    常用UI介绍

    <1>NGUI

    NGUI是一款使用最多的第三方软件,国内大多数的游戏界面UI,都是使用NGUI插件编写出来的

    <2>

    UGUI(Untiy 4.6版本后自带的一套UI系统)

    <3>ONGUI

    现在主要是用于Unity引擎的界面扩展,NGUI和UGUI都是“”所见即所得“,而OnGUI就像是网页编写中HTML和Css样式表

    <Legacy GUI>

    旧版UI,只有俩个组件,分别是GUIText组件和GUIImage组件,分别是文本和图片,公司实际游戏项目开发不会用到

    GUIText组件,主要用于文字的显示

    GUITexture组件

    主要用于图片的显示

    鼠标事件

    OnMosueEnter ()   鼠标进入

    OnMouseExit  ()     鼠标离开

    OnMouseDown ()   鼠标按下

    Color结构体

    Color.red;Color.green;Color.blue;

    特效组件之TrailRenderer(拖尾渲染器)

    它的一个重要用途是体现物体的运动速度,它的位置是在Component->Effects->Teail Renderer

    材质球丢失的颜色为粉红色

    材质球的Shader为Particle/Additive(粒子/添加物)

    Time 设置拖尾持续时间

    美工的黑白图:“黑透白不透”

    特效组件之LineRenderer(线渲染器)

    游戏中常用于渲染激光特效    ,或者用于子弹瞄准

    同TrailRendere一样

    声音组件之AudioSource

    我们导入Unity的所有声音文件,他们的资源类型都是Audio Clip类型

    Unity能使用的音频格式: .aif .wav .mp3 .ogg

    Audio Source音频源组件,你可以将音频源组件当成“音响”

    Play On Awake 唤醒时播放

    Loop 循环

    Mute 静音

    Volume 音量

    Spatial Blend 空间混合 0是2D声音 1是3D声音

    Auido Listener 组件

    声音侦听器,其实就是我们在游戏世界中的耳朵,在Main Camera上会挂载一个Auido Listener组件

    Auido Source 常用函数

    <1>Play() 函数

    播放音频剪辑

    <2>Stop() 函数

    停止播放音频剪辑

    <3>Pause() 函数

    暂停播放音频剪辑

    第二部分:Unity中常用的API函数

    常用API之实例化与销毁

    GameObeject.Instantiate(Object,Vector3,Quaternion);

    Object 是指要实例化的游戏物体

    Vector3既能表示方向又能表示位置,在这里表示要实例化的位置

    Quaternion[四元数]:实例化后物体的旋转状态

    构造随机位置

    Random.Range(min,max);

    在min和max之间随机生成一个随机数

    销毁游戏物体

    GameObject.Destroy(Object,float);  定时销毁某个游戏物体

    Object 要销毁的游戏物体

    float 多少秒后自动销毁

    常用API之Invoke函数调用

    for循环生成宝箱

    for(int i = 0,i<5,i++) {

    GameObject.Instantiate(box,Vector3,Quaternion.Identity);

    }

    一次生成5个宝箱

    Invoke(string,float) : 多少秒后执行某个函数,只会调用一次

    string :要调用的函数名称,用双引号括起来

    float : 多少秒后调用,注意它是浮点数,如5秒,就写成5.0f

    InvokeRepeating(string,float1,float2) :重复调用函数

    string : 要调用的函数名称,用双引号括起来

    float1 : 多少秒后开始调用

    float2 : 以后每隔多少秒调用一次

    Invoke函数的家在哪?

    是Class,类下的函数(方法),字段,属性都可以理解为家庭成员

    Invoke函数属于MonoBehaviour类

    常用API之消息发送

    gameObject.SendMessage(string); 通知这个游戏物体上的脚本执行某个函数

    string : 将要执行的方法名,用双引号括起来

    常用API之协同程序

    在脚本运行过程中,需要执行一些额外的代码,类似开启了一个线程,但协程不是线程,而且协程只能在继承自MonoBehaviour类的子类中使用

    协同程序语法格式

    IEnumerator Task3 () {

    yield return new WaitForSeconds(2);

    Debug.Log("执行任务3"):

    }

    IEnumerator :协同程序的返回值类型

    例如接受这个返回值,private IEnumerator m_ienumerator;

    yield return : 协同程序返回 xxxxx;

    new WaitForSeconds(秒数) : 实例化一个对象,等待多少秒后执行

    开启协同程序

    StartCoroutine(“协同程序方法名”);

    停止协同程序

    StopCoroutine("协同程序方法名")

    常用API之脚本生命周期

    这些生命周期事件是由Unity事先定好的,他们全部定义在MonoBehaviour这个类中,也就意味着只有继承自MonoBehaviour类的脚本,才有这些生命周期事件

    1.Awake ()

    唤醒事件,只能执行一次

    2.OnEnable ()

    启用事件,只执行一次,当脚本组件被启用时执行一次

    3.Start ()

    开始事件,只执行一次

    4.FixedUpdate ()

    固定更新事件,执行N次,每0.02秒执行一次,Update是0.16秒左右执行一次

    5.Update () 

    更新事件,执行N次,每帧执行一次

    6.LateUpdate ()

    稍后更新事件,执行N次,在Update事件之后执行

    7.OnGUI ()

    GUI渲染时间,执行N次,次数是Update事件的俩倍

    8.OnDisable () 

    禁用事件,执行一次。在OnDestroy事件前执行

    9.OnDestroy ()

    销毁事件,执行一次。当脚本所挂载的游戏物体被销毁执行。

    这些时间执行顺序有1-9不变。

    常用API之工具类

    1.Screen 屏幕类 

    2.Time 时间类

    3.Mathf 数学类

    1.Screen 包含了与屏幕相关的数据信息,这个类中常用的属性有Screen.width 屏幕的宽度,Screen.height 屏幕的高度,这俩个值取得是Game窗口的宽度和高度,这让我想到了Camera.main.ScreenPointToWorld(Vector3),将屏幕坐标转换为世界坐标

    2.Time 最常用的属性有Time.time,指的是从游戏开始到现在所用的时间,Time.timeScale,时间缩放,常用于暂停游戏,值为0,暂停游戏,值为0.5,慢放0.5倍,值为1,正常游戏状态

    3.Mathf 包含了各种各样的数学运算相关的函数,常用的函数有Math.Abs() 取绝对值,Mathf.Max 取最大值,Mathf.Min() 取最小值,Mathf.Round() 四舍五入

    Mathf.Lerp(float a,float b,float t) : 插值运算

    基于t返回a~b之间的值,t的取值范围是0~1,t=0时,返回a,t=0.5时,返回a和b的正中间值,t=1时返回b

    例如 a = Mathf.Lerp(a,10,Time.deltaTime) 

    a~10的范围不断缩小,a的值固定增长,最后会无限接近于10

    它的目的是实现"平滑过渡"

    第三部分 物理射线

    物理射线?

    从屏幕的一个点发射一条无限长的射线,这根射线会与场景中的其他游戏物体身上的碰撞体组件碰撞,触发某些函数事件,射线即结束

    由于射线会与物理组件Colider发生交互,所以"射线"也被称为"物理射线"

    Camera.main 代表Tag标签为"Main Camera"的摄像机的Camera组件

    Camera.main.ScreenPointToRay(Vecotor3)

    摄像机Camera组件(对象)下的一个方法

    往鼠标位置发射一条射线的完整代码:

    private Ray ray;

    private RaycastHit hit;

    ray = Camera.main.ScreenPointToRay(Input.mousePosition);

    检查射线与其他物体的碰撞

    RaycastHit     用于存储射线的碰撞信息

    if(Physics.Raycast(ray,out hit))

    {

             要执行的代码;

    }

    Physics.Raycast 物理类下边有一个射线检查的方法,这个方法有16种重载方式,这是第3种

    实例运用之打砖块

    for循环嵌套实例化一堵墙

    for(int l = 0,i < 10,i++)

    {

    for(int h = 0,h < 10,h++)

    {

    GameObject.Instantiate(object,new Vector3(l,h,0),Quaternion.Indentity);

    }

    }

    这段代码会通过预制体实例化一堵10x10的墙

    RaycastHit.point 获取射线的碰撞点

    Vector3向量计算方向:

    Vector3(终点) - Vector(起点) = 方向(起点像终点)

    让砖块五颜六色

    GameObject go = GameObject.Instantiate(object,new Vector3(l,h,0),Quaternion.Indentity);

    go.GetComponent.material.color = new Color(Rndom.Range(0.0f,1.0f),Random.Range(0.0f,1.0f),Random.Range(0.0f,1.0f));

    UnityRGB的取值范围是0~1;

    Debug绘制射线,只能在Scene视图下看到,具体代码为:

    Vector3 dir = hit.point - m_Transform.position; 

    Debug.DrawRay(m_Transform.position,dir,color.red);

    第四节 飞盘射击案例

    飞盘射击之案例分析

    1.UI展示

    游戏开始UI : 游戏名称 玩法介绍 开始游戏 退出游戏 

    游戏UI : 得分 倒计时

    结束UI : 游戏结束 总计得分 重新开始

    2.主角控制 物理射线 碰撞函数 

    3.AI控制 随机生成障碍物

    4.音效特效

    5.调整灯光,摆放资源位置

    飞盘射击案例之主角控制

    手臂朝向碰撞点代码

    Transform.LookAt(Vector3) : 朝向世界中的一个点

    场景模型添加碰撞器

    Mesh Colider组件,使用制作好的简模,降低物理运算消耗,提高游戏性能

    Vertices(verts) : 顶点个数,Mesh网格是由顶点组成面,面组成体,Vertices个数越少,计算量越小

    控制手臂的旋转中心

    新建空物体的方法,用父物体控制子物体,将脚本挂载带父物体身上

    从枪口添加激光特效

    新建一个空物体,重命名,添加LineRenderer组件,设置相关属性

    代码如下:

    LineRenderer.SetPosition(int,Vector3) : 设置线的位置

    int:0是起点,1是终点

    Vector3: 位置

    完整代码如下:

    LineRenderer.SetPosition(0,m_transform.position);

    LineRenderer.SetPosition(1,hit.point);

    飞盘案例之飞盘射击

    Transform.parent   属性,当前游戏物体的父物体

    Transform.GetComponentsInChildren<T>(); 获取所有子物体的某个组件

    GameObejct.AddComponent<T>(); 给脚本所在游戏物体添加组件

    Transform.SetParent(Transform); 将当前物体设置为另一个物体的子物体

    添加背景音效

    主摄像机添加音效

    添加射击音效 如果按下鼠标左键就播放一次

    飞盘射击之游戏管理器

    UI界面的搭建

    StartUI:

    GUIText : 开始游戏

    GUIText : 退出游戏

    GUIText : 玩法介绍 

    GameUI:

    GUIText : 总得分

    GUIText : 倒计时20s

    EndUI:

    GUIText : 游戏结束

    GUIText : 重新开始

    GUIText : 得分

    游戏管理器 GameManager Scripts

    ①创建游戏状态枚举:开始,游戏,结束

    public enum GameState {

    Start,

    Game,

    End

    }

    ②查找获取三组UI的引用,并控制他们的显示次序

    private GameObject m_startUI;                           //定义三个GameObject类型进行接收

    private GameObject m_gameUI;

    private GameObject m_endUI;

    void Start () {

        m_startUI = GameObject.Find("StartUI");          //查找组件 GameObject.Find() ,返回值类型为GameObject

        m_gameUI = GameObject.Find("GameUI");

        m_endUI = GameObject.Find("EndUI");

    }

    ③定义一个字段存储当前的游戏状态

    private GameState gameState;

    ④定义一个切换游戏状态的方法

    public void ChangeGameState(GameState state) //传递过来一个GameStae参数(Start,Game,End),取名state

        {

                gameState = state;                                    //存储传递过来的状态,用定义的引用gameState存储枚举的GameState(Start,Game,End)                 

            if (gameState == GameState.Start)               //开始

            {

                m_startUI.SetActive(true);                         //激活StartUI界面

                m_gameUI.SetActive(false);                     //关闭GameUI界面

                m_endUI.SetActive(false);                        //关闭EndUI界面

                m_bg_audioSource.Stop();                       //停止播放背景音乐

                m_weapon.ChangeCanMove(false);           //获取到Weapon脚本组建后,点获取它的ChangeCanMove方法,里面有俩个参数(true和false)

                m_Weapon.SetActive(false);                    //禁用Weapon对象的所有功能,不显示手臂

                m_feiPan.StopCreat();                              //调用FeiPanGameManager中的StopCreat()方法,即StopCreat方法里的CancelInvoke()

                m_guitext_score.text = "得分:" + score;  //同步重置得分的UI

            }

            else if (gameState == GameState.Game)        //游戏中

            {

                m_startUI.SetActive(false);                       //关闭StartUI

                m_gameUI.SetActive(true);                      //激活GameUI

                m_endUI.SetActive(false);                        //关闭EndUI

                m_bg_audioSource.Play();                      //播放背景音乐

                m_weapon.ChangeCanMove(true);          //激活手臂,ChangeCanMove方法里有俩个布尔值,默认为false,如果为true,默认会发射射线,检测碰撞,添加物理组件,自                                                                          动销毁

                m_Weapon.SetActive(true);                    //激活weapon对象,显示手臂

                m_feiPan.enabled = true;                        //激活FeiPanGameManager脚本组件,生成飞盘

                m_feiPan.StartCreat();                            //调用FeiPanManager脚本组件里的StartCreat()方法,即InvokeRepeating()

                StartTime();                                           //调用StartTIme() 方法

            }

            else if (gameState == GameState.End)        //结束

            {

                m_startUI.SetActive(false);                  //关闭StartUI界面

                m_gameUI.SetActive(false);                //关闭GameUI界面

                m_endUI.SetActive(true);                    //激活EndUI界面

                m_bg_audioSource.Stop();                 //停止播放背景音乐

                m_weapon.ChangeCanMove(false);     //禁用ChangeCanMove方法,包括发射射线,物理射线检测,设置LineRenderer的Position,检测碰撞,射击音效,添加物理组                                                                          件,自动销毁     

                m_Weapon.SetActive(false);              //禁用Weapon对象的所有功能,不显示手臂

                m_feiPan.StopCreat();                       //停止生成飞盘,即CancelInvoke

                m_feiPan.Disapper();                        //立即销毁场景内的所有游戏物体 transform.gameObject,GetComponentInChildren<Transform>(); 

    飞盘射击案例之界面逻辑

    ①开始界面逻辑

              private GameManager gameManager;                    //定义一个GameManager接收脚本

    void Start () 

        {

              gameManager = GameObject.Find("UI").GetComponentInChildren<GameManager>();   //获取UI对象下的GameManager脚本组件

        }

    void OnMouseDown()                         //鼠标按下事件

        {     

            gameManager.ChangeGameState(GameManager.GameState.Game);          //调用GameManager下的ChangeGameState方法

        }

    ②游戏界面逻辑

    1.新建字段存储分数

        private int score = 0;                            //定义一个int类型的字段存储分数

    2.定义一个增加分数的公开方法

    public void AddScore()

        {

            score += 1;                                     //分数+1

            m_guitext_score.text = "得分:" + score;      //同步GameUI下的GameScore的GUIText组件

        }

    3.在武器射击时调用此方法

    if (hit.collider.tag == "FeiPan" && Input.GetMouseButtonDown(0))      //碰撞道德游戏物体的Colider的Tag标签为FeiPan

                {

                        m_gameManager.AddScore();                                             //调用增加分数的方法

               }

    4.控制UI显示分数

    public void AddScore()

        {

            score += 1;                                                             //分数+1

            m_guitext_score.text = "得分:" + score;          //同步GameUI下的GameScore的GUIText组件的text文本

        }

    5.倒计时

       private float time = 20;                //定义时间

       void Update()                               //是在Update中的方法,逐帧调用

        {

            if (satrttime)                           //bool值为True

            {

                time -= Time.deltaTime;                                                                      //倒计时效果

                m_guitext_time.text = "时间:"+ time + "s"                                      //同步倒计时UI,即GameUI下的GameTimeUI的GUIText的text文本

            }

    }

    飞盘射击之案例总结

    结束界面逻辑

    1.倒计时为0,修改游戏状态,并且将倒计时重置

    if (time <= 0)

                {

                    ChangeGameState(GameManager.GameState.End);                  //切换到EndUI

                    m_guitext_end.text = "总计得分:" + score;                                   //同步分数

                    satrttime = false;                             //重置时间和分数

                    time = 20.0f;                  

                    score = 0;

               ]

    2.结束界面显示总分数

        m_guitext_end.text = "总计得分:" + score;

    3.重新开始按钮

            private GameManager m_gamemanager;                 //定义一个GameManager类型接收GameManager脚本组件

        void Start (){

            m_gamemanager = GameObject.Find("UI").GetComponent();          //获取UI对象下的GameManager组件

           }

       void OnMouseDown()                                                     //鼠标按下事件

        {

            m_gamemanager.ChangeGameState(GameManager.GameState.Start);             //返回StarUI,即重新开始按钮

        }

    4.细节调整和优化 for循环删除场景内游戏物体

    public void Disapper() { 

               Transform[] fp = transform.gameObject.GetComponentsInChildren();                  //取得当前组件的对象下的所有子对象的Transform组件

               for (int i = 1; i < fp.Length; i++)                                                                                   //i = 1,防止父物体身上的FeiPanManager脚本组件被删掉

               {

                GameObject.Destroy(fp[i].gameObject);                                                               //删除所有子物体

               }

        }

    本篇完~~~~~~~~~~~

    相关文章

      网友评论

          本文标题:《飞盘射击》案例总结

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