3D游戏编程与设计作业09
UGUI基础
画布
基础概念
- 画布(
Canvas):是绘图区域,同时是UI元素的容器。容器中UI元素及其子UI元素都将绘制在其上。拥有Canvas组件的游戏对象都有一个画布,它空间中的子对象,如果是UI元素将渲染在画布上。 - UI元素采用像素单位表示位置和尺寸
- UI元素的显示顺序:画布种的UI元素按照它们在层次结构中出现的顺序绘制。如果两个UI元素重叠,后面的元素将出现在较早的元素之上。因此,最后一个孩子显示在最上面。
要更改这种显示顺序,可以通过直接拖动它们在Hierarchy视图中的位置,也可通过Transform组件的方法在脚本中控制,如SetAsFirstSiling,SetAsLastSibling,SetSiblingIndex - 渲染模式(
Render Mode):画布组件有渲染模式设置,可用于使其在屏幕空间(Screen Space)或世界空间(World Space)中渲染- 屏幕空间 - 叠加(Screen Space - Overlay)
将UI元素放置在场景顶部渲染的屏幕,画布会自动更改大小匹配屏幕。Canvas默认中心点为屏幕中心! - 屏幕空间 - 相机(Screen Space - Camera)
画布放在制定的渲染摄像机前,如100的位置,画布会自动匹配为屏幕分辨率。Canvas默认中心点为屏幕中心! - 世界空间(World Space)
画布行为与场景中的其他任何对象一样,UI元素将放置在其他对象的前面或后面渲染。画布大小和位置任意设置。
- 屏幕空间 - 叠加(Screen Space - Overlay)
测试渲染模式
-
创建一个
Button对象:GameObject->UI->Button -
创建一个
Cube对象 -
检查、设置以下对象属性
Main Camera的Position=(0,1,-10)Canvas::Button的(PosX, PosY, PosZ) = (0,0,0)Cube的Position=(0,0.5,0)
-
使用鼠标中间滚轮在场景视图中缩小,直到看到整个画布,中间有一个Button,如图所示:

-
选择
Canvas对象的Inspector面板中Canvas组件- 设置
Render Mode为Screen Space - Overlay - 结果:在
Game视图中,可以看到Button在Cube前面

- 设置
-
选择
Canvas对象的Inspector面板中Canvas组件- 设置
Render Mode为Screen Space - Camera - 设置
Render Camera为Main Camera(拖过去赋值)

结果:在
Game视图中可以看到Button在Cube后面

- 设置
-
选择
Main Camera:- 在
Camera组件面板中修改Filed of View - 结果1:在
Game视图中,Cube大小发生变化,而Button保持不变

- 结果2:在
Scene视图中,画布随着视口自动改变大小

- 在
UI布局基础
基本概念
每个UI元素都被表示为一个矩形,为了相对于Canvas和其他UI元素实现定位,Unity在Transform基础上定义了Rect Transform(矩形变换)支持矩形元素在2/3D场景中变换。
- 矩形变换
- 位置和尺寸应使用像素,以匹配素材
- Pivot/旋转点/轴心:旋转点在场景视图中显示为蓝色圆圈,用规范化坐标表示位置。修改
Rotation属性,矩形围绕此点旋转。 - Anchors/锚点:锚点在场景视图中显示为四个小三角形手柄(四页花)。每个叶子位置对应矩形的四个顶点。当锚点随父对象变换时,矩形的顶点与对应的锚点相对位置必须保持不变
锚点练习
- 将场景另存为
Scene2 - 将场景视图设置为2D模式

- 使用鼠标中间滚轮在场景视图中缩小,直到看到整个画布,中间有一个Button
- 将
Canvas的Render Mode设为World Space,以便改变父对象(画布)的大小- 测试结果1:UI元素锚定到父级的中心。该元素保持到中心的固定偏移量

- 测试结果2:UI元素锚定在父级的右下角,该元素保持到右下角的固定偏移量

- 测试结果3:左侧角落的UI元素锚定在父级的左下角,右侧角落锚定在右下角,则元素的角落保持固定的偏移到它们各自的锚点

- 测试结果1:UI元素锚定到父级的中心。该元素保持到中心的固定偏移量
- 实现父子元素的等比缩放的方式:选择
Canvas,直接在场景视图中对Canvas进行缩放即可
UI组件与元素
基本概念
UI部件都是用Script开发的自定义组件。包括在UI、Layout和Rendering等分类中。
- 可视化组件:包括
Text:显示文本的文本区域。可以设置字体样式、大小等文本功能Image:显示图片的区域。可以设置GUI精灵、色彩Raw Image:原始图像采用纹理,进行UV矩形贴图Mask:不是一个可见的UI控件。它将子元素限制(即“掩蔽”)为父元素的形状。如果孩子比父控件大,那么只有适合父节点Mask的部分是可见的Effects:应用各种简单的效果,例如简单的投影或轮廓
更多详细说明可参考官方文档
- UI交互元素:UI交互元素是GameObject,它拥有UI交互组件、UI可视化组件及相关组件的组合,以及一些UI子元素构成,以方便用户在设计场景中创建交互界面
ButtonToggleToggle GroupSliderScrollbarDropdownInput FieldScroll Rect(Scroll View)
更多详细说明可以参考官方文档
Mask练习
- 将场景另存为
Scene3,将除Main Camera和Directional Light以外的对象删掉 - 将如下所示的图片拖入
Assets/Texture目录中,作为纹理图像

- 创建
Panel对象:GameObject->UI->Panel - 在
Panel下添加Raw Image对象:右键Panel->UI->Raw Image - 将前面的纹理图像拖入
Raw Image的Textrue插槽中

- 将场景视图设置为
2D,并缩放至能看到整个画布

- 选择
Panel对象- 在
Rect Transform组件选择Anchor Presets为(middle, center)

- 用
Rect Tool,将Panel与图片的大小调为一致

- 添加
Mask组件 - 选择
Image组件,选择Source Image为Knob
- 在
- 在
Game视图中,可看到如下效果图:

动画练习
- 添加
Animation编辑视图:Window->Animation->Animation - 选择
Raw Image - 在视图
Animation中,点击create按钮,则系统将在该对象上创建动画组件、动画控制器、动画文件,将文件保存为tets1.animAdd Property->Rect Transform->Archored Position->+
- 选择
Scene视图,移动Raw Image到Panel左边

- 选择
Animation视图,(记得先开启录制)在0s位置添加关键帧,将播放位置标线放置在最后 - 选择
Scene视图,移动Raw Image到Panel右边

- 选择
Animation视图,在最后位置添加关键帧 - 运行动画:

富文本测试
为了显示格式复杂的文字,Unity提供了类似HTML标签,控制字体、字号、颜色。
- 在
Canvas下添加Text元素 - 在
Text组件中输入:We are <color=green>green</color> with envy - 结果:

简单血条
给动画人物Ethan添加Health Bar
- 将场景另存为
Scene4,将除Main Camera和Directional Light以外的对象删掉 - 在
Assets Store中下载并导入Standard Assets - 添加一个
Plane对象:GameObject->3D Object->Plane - 将目录
Assets/Standard Assets/Characters/ThirdPersonCharacter/Prefabs下的ThirdPersonController预制拖放入场景中,重命名为Ethan - 检查以下属性:
Plane的Transform的Position=(0,0,0)Ethan的Transform的Position=(0,0,0)Main Camera的Transform的Position=(0,1,-10)
- 为
Ethan添加画布子对象:右键Ethan->UI->Canvas - 添加滑条子对象作为血条:右键
Ethan的子对象Canvas->UI->Slider - 选择
Ethan的Canvas,在Inspector视图中,- 设置
Canvas组件Render Mode为World Space - 设置
Rect Transform组件(PosX, PosY, Width, Height)为(0,2,160,20),此外Scale为(0.01,0.01,1)
- 设置
- 运行效果:

- 展开
Slider- 选择
Handle Slider Area,在Inspector中反勾选该对象,在层级视图中它将变灰 - 选择
Background,在Inspector中反勾选该对象,在层级视图中它将变灰 - 选择
Fill Area的Fill,修改Image组件的Color为红色

- 选择
- 选择
Slider的Slider组件- 设置
Max Value为100 - 设置
Value为75

- 设置
- 给
Canvas挂载脚本LookAtCamera.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class LookAtCamera : MonoBehaviour { // Update is called once per frame void Update() { this.transform.LookAt(Camera.main.transform.position); } } - 运行效果:

血条(Health Bar)的预制设计
UGUI实现
- 用UGUI制作血条的方式见前面简单血条部分
- 将
Ethan的子对象Canvas拖入Assets/Prefabs制成预制,重命名为UGUIHealthBar
IMGUI实现
-
场景另存为
Scene6,去除多余的对象,保留Main Camera,Directional Light和Plane -
创建一个空对象:
GameObject->Creat Empty,并重命名为IMGUIHealthBar -
创建脚本
IMGUIHealthBar.cs-
借助
HorizontalScrollbar(水平滚动条)实现// 用水平滚动条的宽度作为血条的显示值 GUI.color = Color.red; GUI.HorizontalScrollbar(HealthBar, 0, health, 0.0f, maxHealth); -
使用
Mathf.Lerp插值计算血量,以实现血条值平滑变化,而非突变if (GUI.Button(HealthUp, "+")) { resulthealth = resulthealth + 0.1f > 1.0f ? 1.0f : resulthealth + 0.1f; } if (GUI.Button(HealthDown, "-")) { resulthealth = resulthealth - 0.1f < 0.0f ? 0.0f : resulthealth - 0.1f; } //插值计算health值,以实现血条值平滑变化 health = Mathf.Lerp(health, resulthealth, 0.05f); -
让滚动条跟随父对象运动
获取父对象的位置:private Transform father; ... void Start() { father = this.transform.parent.transform; ... }根据父对象的位置设置滚动条的位置:
//血条区域 HealthBar = new Rect(Screen.width / 2 + father.position.x * father.localScale.x * 100 - father.localScale.x * 10, Screen.height / 2 + (father.position.z - father.localScale.y * 7) * father.localScale.z * 10, father.localScale.x * 100, father.localScale.z * 10); //加血按钮区域 HealthUp = new Rect(Screen.width / 2 + father.position.x * father.localScale.x * 100 - father.localScale.x * 30 , Screen.height / 2 + (father.position.z - father.localScale.y * 7) * father.localScale.z * 10 , father.localScale.x * 20, father.localScale.z * 10); //减血按钮区域 HealthDown = new Rect(Screen.width / 2 + father.position.x * father.localScale.x * 100 + father.localScale.x * 90, Screen.height / 2 + (father.position.z - father.localScale.y * 7) * father.localScale.z * 10, father.localScale.x * 20, father.localScale.z * 10);
-
-
将脚本
IMGUIHealthBar.cs和前面已经写好的LookAtCamera.cs挂载到IMGUIHealthBar下 -
将
IMGUIHealthBar拖入Assets/Prefabs制成预制 -
运行效果:

完整项目传送门
两种实现的比较
| UGUI | IMGUI | |
|---|---|---|
| 优点 | 1. 所见即所得(WYSIWYG)设计工具,设计师也能参与程序开发 2.支 持多模式、多摄像机渲染 3. UI 元素与游戏场景融为一体的交互 4. 面向对象的编程 | 1. 符合游戏编程传统 2. 在修改模型,渲染模型这样的经典游戏循环编程模式中,在渲染阶段之后,绘制 UI 界面无可挑剔 3. 这样的编程既避免了 UI 元素保持在屏幕最前端,又有最佳的执行效率,一切控制掌握在程序员手中 |
| 缺点 | 1. 没有 UIWrap 来循环 scrollview 内容 2. 暂时没有Tween组件 | 1. 传统代码驱动的 UI 面临效率低下 2. 难以调试 |
使用方式
创建一个ThirdPersonController对象,将预制UGUIHealthBar或IMGUIHealthBar拖到层级面板中,使之成为ThirdPersonController对象的子对象即可
300

被折叠的 条评论
为什么被折叠?



