Unity之UI和登陆界面与暂停界面

Unity————UI和登陆界面与暂停界面

接触了Unity制作不管是程序还是游戏都避免不了UI的制作,但是在网上搜的UI制作的学习过程,额…一言难尽,就像是拼图一样在那一块块搜索然后再将它拼装起来,痛苦万分.因此撰此文以记录我的UI的学习过程.首先要理解的就是UI设计的含义,UI包括登陆界面,暂停界面等等但不只有这些东西.UI称之为(User Interface),是指对软件的人机交互,操作逻辑,界面美观的整体设计.UI设计的目的是操作变得更舒适简单自由.一般来说在游戏中接触最多的UI就是登陆界面,暂停界面,设置界面,教程界面之类的,或者说游戏右上角假如有一个暂停按键(开挂按键)那么它也可以称之为UI.

参考网址:https://docs.unity.cn/cn/current/Manual/UIToolkits.html

一般来说在开始搜索“UI的制作过程”都是在要制作登陆界面或者暂停界面遇到了瓶颈,所以本文将着重于如何快速的利用unity的内置工具制作出一个能用能看的简易UI,用到的是unity教程里的unity UI而不是unity工具包,若在自行查阅文档过程中可以着重看这一部分.

如果目标是为了制作一个登陆界面,那么我们现在最需要的就是一个界面,一个按钮,然后按下这个按钮从界面进入到游戏中(假设游戏为场景SceneGame并且已经制作完成),那么登陆界面的操作就是创建一个新的场景SceneLogin然后里面有个按钮Button,按下Button后场景切换(利用UnityEngine.SceneManagement)切换到SceneGame,这就是一个简单的登陆界面.暂停界面则是设备检测到一个按键被按下(比如Esc),然后让整个游戏暂停,再调出一个界面,上面有两个按钮“恢复游戏”与“退出游戏”,前者让一切恢复正常,后者则是直接退出游戏.这篇文章的目的就是建立这两个界面.

Canvas画布

只要在百度这个离谱的搜索引擎上搜索过unity的UI制作就不会对这个词感到陌生
参考:https://blog.csdn.net/qq_45548042/article/details/121011915.
一切UI的控制部件都是在canvas进行布置的.令人疑惑不解的是为什么所有的UI组件都需要在canvas上进行布置呢?官方的说法如下:

画布 (Canvas) 是应该容纳所有 UI 元素的区域。画布是一种带有画布组件的游戏对象,所有 UI 元素都必须是此类画布的子项。
创建新的 UI 元素(如使用菜单 GameObject > UI > Image 创建图像)时,如果场景中还没有画布,则会自动创建画布。UI 元素将创建为此画布的子项。
画布区域在 Scene 视图中显示为矩形。这样可以轻松定位 UI 元素,而无需始终显示 Game 视图。
画布 使用 EventSystem 对象来协助消息系统。

以我浅薄的理解,canvs设计的必要性有以下几条:

  • 方便渲染
  • 定位UI元素而不需要显示Game视图
  • 协助消息系统
  • 对不同分辨率的屏幕尽可能显示出一致的界面(锚点功能)

Canvas总共有三种模式,第一种模式(Screen Space-Overlay)是camera镜头里只有canvas,就相当于我们所做的界面操作,unity只会渲染canvas而不会渲染其他的物品,大部分登陆界面用的是第一种模式.第二种模式(Screen Space-Camera)canvas会一直放在camera的前面,显示在镜头前面的一定距离的地方,它不会影响正常场景的渲染,视觉感觉来说就是你面前一直存在一个具有一定大小的界面.第三种模式(World Space),Canvas就被当成了正常的物品对象,跟一个正方体没有什么区别,也不会随着摄像头的移动而移动,个人理解为在制作3D人物上的血条,或者是很炫酷的那种控制界面用这种Canvas比较多.

登陆界面

哦,要不我们开始试试创建一个登陆界面?

首先在“项目”界面右键创建一个新场景(命名为SceneLogin),然后再在左侧的“层级”界面右键-UI-按钮,因为所有的UI组件都会在Canvas里面,所以Unity会自动帮你创建一个Canvas.应该能注意到按钮挂在Canvas下面,而按钮下面还挂着一个Text,这是控制你按钮上的字体显示的.有可能你的按钮上没有显示字体,这是因为你还没有把字体文件库导入进去,字体文件在Text里的Font Asset里进行设置,点开来会发现里面是空.这时候点击菜单栏(就最上面那一排)的窗口——TextMeshPro——导入TMP基本资源,就可以将字体文件导入进去了,此时字体就配置好了.这就是我们的登陆界面,虽然它什么功能都没有,但至少是像一个登陆界面了.里面的细节可以根据手册自己摸索,这不是我们的主线任务,我们就不再进行赘述了

创建按钮参考:https://www.csdn.net/tags/MtjaUgysNDU3MzMtYmxvZwO0O0OO0O0O.html

按钮控制

现在我们给按钮加上一个脚本附件,我想这个操作对于依葫芦画瓢做过一次项目的人(如果没有建议去做一下)已经是轻车熟路了

using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine;

public class LoadScene: MonoBehaviour
{
    Button LoginButton;
    public void OnClickLogin()
    {
        SceneManager.LoadScene(1);
    }
    private void Awake()
    {
        LoginButton = GetComponent

这里面用到了UnityEngine.UIUnityEngine.SceneManagement,分别用作给按钮加上监听函数,以及对场景进行切换,注意要对(Building Setting 生成设置)进行操作

切换场景参考:https://blog.csdn.net/weixin_44831924/article/details/100055216
这篇文章里面的一些操作已经过时了,但是里面对生成设置的操作有必要阅读

现在我们一个最最最最基础的登陆界面就制作完成了,但是我们不能只知其然不知其所以然,所以接下来我们会对代码进行深一步的挖掘

SceneManager

SceneManager是对场景进行管理的类,具体的成员和方法详细见附录,用的最多的就是LoadScene,利用场景编号或者场景名称对场景进行切换,这里要注意下其与LoadSceneAsync的区分,可参考这篇文章:https://blog.csdn.net/qq_42462109/article/details/83096135?spm=1001.2014.3001.5502.在loadscene的过程中还可以指定加载哪种类型的场景,可以加载单模式和附加模式,单模式就是普通的切换场景,附加模式使得屏幕中中包含两个场景,比如说做背包血条栏可以利用这种模式.注意与MergeScene的区别,合并场景会破坏原场景,这是一种破坏性行为.

另外,在用附加模式的加载场景的过程中,要注意活动场景的设置,对应方法是SetActiveScene,因为一些操作都是需要对应活动场景的,比如新建一个Object,烘焙等等操作,都是对应活动的场景,参考https://www.jianshu.com/p/f897ac4376f9

using UnityEngine;
using UnityEngine.SceneManagement;

public class ExampleClass : MonoBehaviour
{
    void Start()
    {
        // Only specifying the sceneName or sceneBuildIndex will load the Scene with the Single mode
        SceneManager.LoadScene("OtherSceneName", LoadSceneMode.Additive);
    }
}

Button

这里的Button成员指UnityEngine.UI.Button,参考文档:https://docs.unity.cn/cn/2019.2/ScriptReference/UI.Button.html

Button的继承树如下:UI.Button->UI.Selectable->EventSystem.UIBehaviour->MonoBehaviour

MonoBehaviour大家都很熟了,老朋友了,所有的Unity脚本都派生于此类.UIBehaviour手册上写的是具有Unity生命周期函数的受保护实现的基准行为,将里面类似Start之类的方法添加protected关键字,相当于Unity已经实现这些方法并且不希望有人去动它.UI.Selectable为简单的可选择对象(Selectable Object),通过它创造可选择的对象,比如Button.(详细见附录)

对于Button来说,最重要的就是里面的成员onClick,这是一个当按钮被按下后所触发的Unity的事件,它的类型是UI.Button.ButtonClickedEvent,继承于UnityEvent,详情可以看附录里记录的UnityEvent的用法,最常用就是增加监听函数的方法AddListener.

哦如果想用一点复杂的按钮的用法的话,可以尝试了解下OnPointerClick回调函数,它是鼠标按下后的回调函数Unity会传过来一个EventSystems.PointerEventData类型的数据称作eventData,通过重载这个回调函数可以实现更加复杂的代码,参考代码如下:

//Attatch this script to a Button GameObject
using UnityEngine;
using UnityEngine.EventSystems;

public class Example : MonoBehaviour, IPointerClickHandler
{
    //Detect if a click occurs
    public void OnPointerClick(PointerEventData pointerEventData)
    {
        //Use this to tell when the user right-clicks on the Button
        if (pointerEventData.button == PointerEventData.InputButton.Right)
        {
            //Output to console the clicked GameObject's name and the following message. You can replace this with your own actions for when clicking the GameObject.
            Debug.Log(name + " Game Object Right Clicked!");
        }

        //Use this to tell when the user left-clicks on the Button
        if (pointerEventData.button == PointerEventData.InputButton.Left)
        {
            Debug.Log(name + " Game Object Left Clicked!");
        }
    }
}

关于PointerEventData的文档:https://docs.unity.cn/cn/2019.2/ScriptReference/EventSystems.PointerEventData.html

暂停界面

接下来便是制作暂停界面,暂停界面的要求是按下Esc后,游戏停止,并跳出界面,上面应该至少含有两个按钮,一个按钮为Resume用于恢复游戏,另一个按钮为Quit用于退出游戏.参考文章https://blog.csdn.net/dangoxiba/article/details/122922065

首先我们创建一个Canvas,并且在Canvas下创建两个按钮,分别命名和调整里面的字体内容为Resume和Quit.接着编写以下脚本,并且将其添加为Canvas的组件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PauseMenu : MonoBehaviour
{
    public GameObject QuitButton;
    public GameObject ResumeButton;
    bool isPause=false;
    // Start is called before the first frame update
    void Start()
    {
        QuitButton.SetActive(false);
        ResumeButton.SetActive(false);
    }
    public void QuitEvent()
    {
        Application.Quit(0);
    }
    public void ResumeEvent()
    {
        isPause = false;
        QuitButton.SetActive(false);
        ResumeButton.SetActive(false);
        Time.timeScale = 1.0f;
    }
    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Escape)&& !isPause)
        {
            isPause = true;
            QuitButton.SetActive(true);
            ResumeButton.SetActive(true);
            Time.timeScale = 0.0f;
        }
    }
}

添加到Canvas组件后可以看到组件PauseMenu上有两个属性,将QuitButton和ResumeButton分别拖到里面去.如图所示
Unity之UI和登陆界面与暂停界面_第1张图片
这次我们不用脚本实现事件添加而是手动去添加,选中Button对象,在鼠标单击的栏目下添加Canvas对象,再在右边的事件下选择Canvas对象中的对应的方法,像Resume按钮就选择ResumeEvent方法,Quit按钮选择QuitEvent方法,如图所示
Unity之UI和登陆界面与暂停界面_第2张图片

将Canvas的图层设置为1,一直将其放置在顶层,至此一个最最最基础的暂停界面就完成了,按下Esc即可暂停.

代码详解

此功能的代码并没有太多的新知识点,InputGameObject都是Unity基础知识里了解过的东西,GameObject.SetActive设置对象是否活动,设置为True即活动并且可见,设置为False即不活动且不可见,Input.GetKeyDown检测键盘上是否有按键是否按下,Application.Quit退出播放器程序,对于UnityEngine.Application更多的用法详见用户手册https://docs.unity.cn/cn/2021.3/ScriptReference/Application.html

time里的timescale设置对像物理运动的快慢,可以通过增加或减小timescale来实现感觉上的加速和减速.设置Time.timescale=0.0f即可达到停止效果,反之设置Time.timescale=1.0f恢复正常.关于Time的更多用法详见用户手册https://docs.unity.cn/cn/2021.3/ScriptReference/Time-timeScale.html

附录

UnityEventBase

UnityEvent 的抽象基类。
此类为 UnityEvent 提供了基本功能。

备注:不要看中文解释,去看他英文名字以理解其含义,中文解释跟坨?一样

公共函数:

名称 解释
GetPersistentEventCount 获取已注册的持久性监听器的数量。
GetPersistentMethodName 获取索引处的监听器的目标方法名称。
GetPersistentTarget 获取索引处的监听器的目标组件。
RemoveAllListeners 从事件中删除所有非持久性(即通过脚本创建的)监听器。
SetPersistentListenerState 修改持久性监听器的执行状态。

静态函数:

名称 解释
GetValidMethodInfo 提供了对象、函数名称和参数类型列表;找到匹配的方法。

UnityEvent:UnityEventBase

可以与场景一起保存的0参数持久回调

构造函数
UnityEvent:构造函数。

公共函数:

名称 解释
AddListener 向UnityEvent添加非持久性监听器。
Invoke 调用所有已注册的回调(运行时和持久性)。
RemoveListener 从UnityEvent中删除非持久性监听器。

UnityEvent< T0>: UnityEventBase

同:

  • UnityEvent< T0,T1>
  • UnityEvent< T0,T1,T2>
  • UnityEvent< T0,T1,T2,T3>

这相当于UnityEvent的多参数版本,要注意的是如果需要用这种多参数的版本需要对参数进行覆盖,以下将利用两参数版本进行范例:

using UnityEngine;
using UnityEngine.Events;

[System.Serializable]
public class MyIntEvent : UnityEvent
{
}
public class ExampleClass : MonoBehaviour
{
    public MyIntEvent m_MyEvent;
    void Start()
    {
        if (m_MyEvent == null)
            m_MyEvent = new MyIntEvent();

        m_MyEvent.AddListener(Ping);
    }
    void Update()
    {
        if (Input.anyKeyDown && m_MyEvent != null)
        {
            m_MyEvent.Invoke(5, 6);
        }
    }
    void Ping(int i, int j)
    {
        Debug.Log("Ping" + i + ", " + j);
    }
}

UI.Selectable:EventSystems.UIBehaviour

简单的可选择对象 - 可从中派生,以创建可选择控件。

静态变量:

名称 解释
allSelectables List of all the selectable objects currently active in the Scene.

变量:

名称 解释
animationTriggers 用于此可选择对象的 AnimationTriggers。
animator 便捷函数,用于获取 GameObject 中的 Animator 组件。
colors 用于此可选择对象的 ColorBlock。
image 便捷函数,可将引用的 Graphic 转换为 Image(如果可能)。
interactable 用于启用或禁用对可选择 UI 元素(例如,按钮)进行选择的功能。
navigation 此可选择对象的 Navigation 设置。
spriteState 用于此可选择对象的 SpriteState。
targetGraphic 将过渡的 Graphic。
transition 过渡的类型,当状态更改时将应用于 targetGraphic。

公共函数:

名称 解释
FindSelectable 查找此对象旁边的可选择对象。
FindSelectableOnDown 查找此对象下方的可选择对象。
FindSelectableOnLeft 查找此对象左侧的可选择对象。
FindSelectableOnRight 查找此对象右侧的可选择对象。
FindSelectableOnUp 查找此对象上方的可选择对象。
IsInteractable UI.Selectable.IsInteractable。
OnDeselect 撤消选择并过渡到适当状态。
OnMove 确定应在 4 个移动方向中的哪个方向找到下一个可选择对象。
OnPointerDown 评估当前状态并过渡至按下状态。
OnPointerEnter 评估当前状态并过渡至适当状态。
OnPointerExit 评估当前状态并过渡至正常状态。
OnPointerUp 评估 eventData 并过渡至适当状态。
OnSelect 设置选择并过渡到适当状态。
Select 选择此 Selectable 对象。

SceneManagement.SceneManager

运行时的场景管理。

静态变量:

名称 解释
sceneCount 当前加载的场景总数。
sceneCountInBuildSettings Build Settings 中的场景数量。

静态函数:

名称 解释
CreateScene 在运行时使用给定名称创建一个新的空场景。
GetActiveScene 获取当前活动的场景。
GetSceneAt 获取 SceneManager 的已加载场景列表中索引处的场景。
GetSceneByBuildIndex 从构建索引中获取场景结构。
GetSceneByName 搜索已加载的场景,查找包含给定名称的场景。
GetSceneByPath 搜索所有已加载的场景,查找具有给定资源路径的场景。
LoadScene 按照 Build Settings 中的名称或索引加载场景。
LoadSceneAsync 在后台异步加载场景。
MergeScenes 这会将源场景合并到 destinationScene 中。
MoveGameObjectToScene 将游戏对象从当前场景移至新场景。
SetActiveScene 将场景设置为活动状态。
UnloadSceneAsync 销毁所有与给定场景关联的游戏对象,并将场景从 SceneManager 中移除。

事件:

名称 解释
activeSceneChanged 订阅此事件可在活动场景发生变化时收到通知。
sceneLoaded 向此事件添加委托,以在加载场景时收到通知。
sceneUnloaded 向此事件添加委托以在卸载场景时收到通知。

你可能感兴趣的:(Unity学习笔记,unity,ui,游戏引擎)