《Unity3D高级编程 主程手记》第四章 用户界面(二) UGUI 系统的原理及其组件使用

目录

[UGUI 系统的运行步骤](#UGUI 系统的运行步骤)

过程

问题

[UGUI 的优化](#UGUI 的优化)

[UGUI 系统的组件](#UGUI 系统的组件)

[1、Canvas 组件](#1、Canvas 组件)

[Canvas 的参数 Render Mode(渲染模式)](#Canvas 的参数 Render Mode(渲染模式))

[(1)Overlay 模式------不以 Camera 为基准](#(1)Overlay 模式——不以 Camera 为基准)

[(2)Screen Camera模式------以 Camera 为基准](#(2)Screen Camera模式——以 Camera 为基准)

[(3)World Space 模式------以 3D 世界为基准](#(3)World Space 模式——以 3D 世界为基准)

[2、Canvas Scaler 组件](#2、Canvas Scaler 组件)

[3、Graphic Raycaster 组件](#3、Graphic Raycaster 组件)

[4、EventTrigger 组件](#4、EventTrigger 组件)

[5、Image、RawImage 组件](#5、Image、RawImage 组件)

[6、Mask、RectMask2D 组件](#6、Mask、RectMask2D 组件)

7、其他组件


UGUI 系统的运行步骤

UGUI 是在 3D 网格下建立起来的 UI 系统 ,它的每个可显示的元素都是通过3D 模型网格 的形式来构建起来的。当 UI 系统被实例化时,UGUI 系统首先要做的就是构建网格

过程

Unity3D 在制作一个图元,或者一个按钮,或者一个背景时,都会先构建一个方形网格,再将图片放入网格中。可以理解为制造了一个 3D 模型,用一个网格绑定一个材质球,材质球里存放要显示的图片。

问题

如果每个元素都生成一个模型并且绑定一个材质球存入一张图片的话,那么界面上成千上万个元素就会拥有成千上万个材质球,以及成千上万张图。如果 GPU 对每个材质球和网格都进行渲染,将会导致 GPU 负担重大,我们可以理解为一个材质球一个 drawcall 会导致 drawcall 过高。

**drawcall:**绘制调用,引擎向硬件发送渲染命令以绘制图形对象的过程。

UGUI 的优化

它将一部分相同类型 的图片集合起来合成一张图 ,然后将拥有相同图片、相同着色器的材质球指向同一个材质球,并且把分散开的模型网格合并起来,这样就生成了几个大网格和几个不同图集的材质球,以及少许整张的图集。

**图集:**它把很多张图片放置在一张图集上,使得大量的图片和材质球不需要重复绘制,只要改变模型顶点上的 UV 和颜色即可。

**UV:**分别是图片在显示器水平、垂直方向上的坐标。

UGUI 系统并不是所有的网格和材质球都合并成一个,它只是把相同层级的元素,以及相同层级上的拥有相同的材质球参数的进行合并处理。

合并成一个网格,就相当于是一个静止的模型,如果移动了任何元素,或者销毁了任何元素,或者改变了任何元素的参数,原本合并的网格就不符合新的要求了,于是 UGUI 系统就会销毁这个网格,并重新构建一个。

我们要想方设法合并更多的元素减少重构网格的次数,以达到更少的性能开销目的。

UGUI 系统的组件

1、Canvas 组件

画布,我们把各类元素放在画布上后,Canvas 要做的事情就是合并这些元素。

合并的规则:在同一个 Canvas 里,将相同层级、相同材质球的元素进行合并,从而减少 drawcall。

相同层级不是指 gameobject 上的节点层级,而是覆盖层级。

Canvas 的参数 Render Mode(渲染模式)

(1)Overlay 模式------不以 Camera 为基准
  • 不与空间上的排序有任何关系,空间上的前后位置不再对元素起作用。
  • 它常用在纯 UI 的区域内
  • Sort order 参数在排序时被重点用到,Sort order 参数的值越大,越靠前渲染
(2)Screen Camera模式------以 Camera 为基准
  • 相对比较通用一点,它依赖于 Camera 的平面透视,渲染时的布局依赖于它绑定的 Camera。
  • 想让更多的非 UGUI 元素加入到 UI 中,Screen Camera 模式更加具有优势。
  • 这种模式是实际项目中制作 UI 最常用的模式,不过 UGUI 系统底层针对排序有一些规定 ,如对 z 轴不为0的元素,会单独提取出来渲染,不参与合并。
(3)World Space 模式------以 3D 世界为基准
  • 主要用于当 UI 物体放在 3D 世界中时,比如,一个大的场景中,需要将一张标志图放在一个石块头上。
  • 与 Screen Camera 的区别是,它常在世界空间中与普通 3D 物体一同展示,依赖于截锥体透视(Perspective)Camera。
  • 它的原理与普通物体一样,当 UI 物体在这个 Camera 视野中时,就相当于渲染了一个普通的 3D 图片,只是除了普通的渲染 Canvas 外,还对这些场景里的 UI 进行合并处理。

2、Canvas Scaler 组件

屏幕适配组件,用来指定画布中元素的比例大小。

  • **Constant Pixel Size:**简单指定比例大小。

  • **Scale With Screen Size:**以屏幕为基准的自动适配比例大小的规则。

  • **Constant Physical Size:**以物理大小为基准的适配规则。

在实际手游项目里,设备的屏幕分辨率变化比较大,通常使用以屏幕为基准的自动适配比例大小的 Scale With Screen Size 选项。

3、Graphic Raycaster 组件

输入系统的图形碰撞测试组件,它并不会检测 Canvas 以外的内容,检测的都是 Canvas 下的元素。

当图元素上存在有效的碰撞体时,Graphic Raycaster 组件会统一使用射线碰撞测试 来检测碰撞的元素。也可以设置完全忽略输入的方式来彻底取消点击响应,还可以指定阻止对某些 layers 进行响应。

4、EventTrigger 组件

输入事件触发器,与此脚本绑定的 UI 物体都可以接收输入事件。它主要起到点击响应作用,配合 Graphic Raycaster 进行响应。

5、Image、RawImage 组件

这两个是 UI 里的主要部件,它们可以对图片进行展示,包括图片,图集。

两者的区别:Image 组件仅能展示图集中的图元,但展示的图元可以参与合并;而 RawImage 组件能展示单张图片,但无法参与合并。

通常我们会将小块的图片打包成图集来展示,这样更节省性能也更节省内存,这也是 UGUI 自动集成的功能,每个图片资源都有一个 tag 标记,标记决定了哪些元素会合并到同一张图集内,如果没有 tag 标记,则默认不会合并图集,它自己就是自己的图集。

不使用图集而使用 RawImage 展示单张图片的时,通常都是由于图片尺寸太大 导致合并图集效率太低 ,或者相同类型的图片数量太多 ,导致合并图集后的图集太大,而实际在画面上需要展示的这种类型的图片又很少,图集方式反而浪费大量内存空间,因此使用 RawImage 逐一展示即可。

6、Mask、RectMask2D 组件

遮挡组件,可以将其子节点下矩形区域外的内容剔除,是滚动窗口中最常用的组件。

这两种方式的主要是在剔除的方法 上有所区别, 在实现效果上都是一样的,其中 Mask 使用顶点重构 的方式剔除矩形区域外的部分,而 RectMask2D 则采用着色器的剔除方式,每个元素都有自己的材质球实例和实例参数。

Mask、RectMask2D 的剔除方式存疑,可以参考U3D:Mask和RectMask2D_unity mask和rectmask2d-CSDN博客,具体细节在后面源码分析的章节深入分析。

7、其他组件

其他大部分逻辑组件都是可以重写的,比如按钮组件 Button、切换组件 Toggle、滚动条组件 ScrollBar、滑动组件 Slider、下拉框组件 DropDown、视图组件 ScrollView,如果不想使用它们,觉得它们的功能不够用,也可以用 Image、Mask 等几个核心组件组合后重写。

实际工作中,很多项目都会自定义属于自己的组件。为什么要自定义呢?很多时候,项目里的需求是多样化的,若有自己的组件,在有特殊需求和特殊逻辑时,就能够毫不费劲的更改。所以,大部分项目中都会重写一些组件来用来给自己项目使用,也有一些人总结了这些组件的经验,编写了比较好用的组件开源在 Github 上。

相关推荐
小码狐1 小时前
并查集【数据结构与算法】【C语言版-笔记】
数据结构·笔记·并查集·c语言版
LearnTech_1232 小时前
【学习笔记】手写一个简单的 Spring MVC
笔记·学习·spring·spring mvc
笑鸿的学习笔记4 小时前
工具笔记之生成图表和可视化的标记语言Mermaid
笔记
kissSimple4 小时前
UE行为树编辑器图文笔记
笔记·ue5·编辑器·unreal engine·unreal engine 5
l1x1n04 小时前
DOS 命令学习笔记
笔记·学习·web安全
golitter.5 小时前
Vue组件库Element-ui
前端·vue.js·ui
winds~5 小时前
自动驾驶-问题笔记-待解决
人工智能·笔记·自动驾驶
s_little_monster6 小时前
【QT】QT入门
数据库·c++·经验分享·笔记·qt·学习·mfc
alfiy6 小时前
Elasticsearch学习笔记(六)使用集群令牌将新加点加入集群
笔记·学习·elasticsearch
爱学的小涛6 小时前
【NIO基础】基于 NIO 中的组件实现对文件的操作(文件编程),FileChannel 详解
java·开发语言·笔记·后端·nio