3D游戏编程与设计作业09
3D游戏编程与设计作业09
- UGUI基础
- 画布
- 基础概念
- 测试渲染模式
- UI布局基础
- 基本概念
- 锚点练习
- UI组件与元素
- 基本概念
- Mask练习
- 动画练习
- 富文本测试
- 简单血条
- 血条(Health Bar)的预制设计
- UGUI实现
- IMGUI实现
- 两种实现的比较
- 使用方式
- 其他参考资料
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子元素构成,以方便用户在设计场景中创建交互界面
Button
Toggle
Toggle Group
Slider
Scrollbar
Dropdown
Input Field
Scroll 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.anim
Add 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.cs
using System.Collections; using System.Collections.Generic; using UnityEngine;public class LookAtCamera : MonoBehaviour {// Update is called once per framevoid 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
对象的子对象即可
其他参考资料
潘老师的课程网站 第九章 UI系统
Unity3D学习笔记(四)分别使用IMGUI和UGUI实现血条的预制设计
3D游戏编程与设计作业09相关推荐
- 3D游戏编程与设计作业10
3D游戏编程与设计作业10 环境说明 Unity3D 导航与寻路 Agent 和 Navmesh 练习 Obstacle和Off-Mesh-Link练习 P&D 过河游戏智能帮助实现 状态图 ...
- 3D游戏编程与设计作业六
改进飞碟(Hit UFO)游戏 要求 按 adapter模式 设计图修改飞碟游戏 使它同时支持物理运动与运动学(变换)运动 实现 原项目:3D编程与游戏设计作业五 仅仅对其中的一些类进行改动就能实现. ...
- 3D游戏编程与设计作业6-Unity实现打飞碟游戏改进版(Hit UFO)
改进飞碟(Hit UFO)游戏 游戏内容要求 按adapter模式设计图修改飞碟游戏 使它同时支持物理运动与运动学(交换)运动 编程实践 本次作业直接在上一次打飞碟游戏的基础上增加adapter设计模 ...
- 3D游戏编程与设计作业4-Skybox_牧师与魔鬼进阶版
基本操作演练 下载Fantasy Skybbox FREE,构建自己的游戏场景 直接在上一次作业的Priests and Devils游戏场景中添加天空盒和地形构建场景.首先在Unity Assets ...
- 3D游戏编程与设计作业四
第四次3D编程作业 本次作业源代码链接:点击此处进行跳转 一. 基本操作演练 下载Fantasy Skybox Free,构建自己的游戏场景 场景总览图: 游玩截图: 写一个简单的总结,总结游戏对象的 ...
- 3D游戏编程与设计作业三
第三次3D编程作业 本次作业源代码链接:点击此处进行跳转 1. 简答并用程序验证 游戏对象运动的本质是什么 游戏对象空间属性(坐标.旋转度.大小)的变化 请用三种以上方法,实现物体的抛物线运动 此处我 ...
- 3D游戏编程与设计作业2-太阳系-Priests and Devils
简答题 一.游戏对象运动的本质是什么? 游戏对象的本质是游戏对象每一帧的由空间属性决定的坐标随时间发生改变,其中空间属性包括对象transform属性中的空间位置Position属性.旋转角度Ro ...
- 3D游戏编程与设计作业一
游戏分类与热点探索 使用思维导图描述游戏的分类.(游戏分类方法特别多) 所使用的思维导图绘图工具为mindmaster. 结合手机游戏市场的下载量与排名等数据,结合游戏分类图,描述游戏市场的热点. 华 ...
- 3D游戏编程与设计作业4——使用skybox构建游戏场景
步骤1: 首先下载支持使用Fantacy Skybox FREE 的Unity版本(2021.3) 步骤2:打开unity store, 搜索Fantacy Skybox FREE 并进行下载 步骤3 ...
最新文章
- python新建excel表格-python xlwd对excel(表格)写入详解
- es index 改名_Elasticsearch Index模块
- 基本概率模型和贝叶斯定理
- BZOJ3387栅栏行动
- 【转载】linux进程及进程控制
- 又不能起床python好学吗
- CodeForces 164C Machine Programming 费用流
- 照顾好自己才能照顾好别人_6种照顾数字外观的方法
- 余承东透露华为Mate X发布时间:今年六月上市
- C#.Net工作笔记010---c#中的静态扩展方法_可动态给string等_添加共通方法好用
- 2017年经历的那些灵异事件
- Singleton 与 MonoState 模式
- DPDK 实现的不完全笔记
- Redis未授权访问缺陷让服务器沦为肉鸡
- 360极速浏览器配置Chromedrive
- 【OI备忘录】dalao博文收藏夹
- win10 安装docker msi主板开启虚拟化
- Java知识点总结【6】抽象类和接口
- VS2022写Qt代码遇到的问题之 C2504 “xxx”: 未定义基类 (编译源文件
- B2B2C分布式微服务电商源码(支持:小程序、公众号、H5、IOS、Android)
热门文章
- ESP-C3入门13. SoftAP模式
- Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day35】
- python pc微信 接收信息_GitHub - ericadver/WechatPCAPI: 微信PC版的API接口,可通过Python调用微信获取好友、群、公众号列表,并收发消息等功能。...
- C语言--PTA三天打渔两天晒网问题
- 【Flutter应用】Flutter精仿抖音开源
- JAVA初学之键盘录入
- html搜狐热搜列表仿写,织梦列表页获取热搜排行榜文章
- Java编程基础测题(二十道)
- 如何windows远程控制mac电脑
- SpringBoot:WebSocket实现消息撤回、图片撤回