3D游戏编程与设计作业09

  • UGUI基础
    • 画布
      • 基础概念
      • 测试渲染模式
    • UI布局基础
      • 基本概念
      • 锚点练习
    • UI组件与元素
      • 基本概念
      • Mask练习
      • 动画练习
      • 富文本测试
      • 简单血条
  • 血条(Health Bar)的预制设计
    • UGUI实现
    • IMGUI实现
    • 两种实现的比较
    • 使用方式
  • 其他参考资料

UGUI基础

画布

基础概念

  • 画布(Canvas):是绘图区域,同时是UI元素的容器。容器中UI元素及其子UI元素都将绘制在其上。拥有Canvas组件的游戏对象都有一个画布,它空间中的子对象,如果是UI元素将渲染在画布上。
  • UI元素采用像素单位表示位置和尺寸
  • UI元素的显示顺序:画布种的UI元素按照它们在层次结构中出现的顺序绘制。如果两个UI元素重叠,后面的元素将出现在较早的元素之上。因此,最后一个孩子显示在最上面
    要更改这种显示顺序,可以通过直接拖动它们在Hierarchy视图中的位置,也可通过Transform组件的方法在脚本中控制,如SetAsFirstSilingSetAsLastSiblingSetSiblingIndex
  • 渲染模式(Render Mode):画布组件有渲染模式设置,可用于使其在屏幕空间(Screen Space)或世界空间(World Space)中渲染
    • 屏幕空间 - 叠加(Screen Space - Overlay)
      将UI元素放置在场景顶部渲染的屏幕,画布会自动更改大小匹配屏幕。Canvas默认中心点为屏幕中心!
    • 屏幕空间 - 相机(Screen Space - Camera)
      画布放在制定的渲染摄像机前,如100的位置,画布会自动匹配为屏幕分辨率。Canvas默认中心点为屏幕中心!
    • 世界空间(World Space)
      画布行为与场景中的其他任何对象一样,UI元素将放置在其他对象的前面或后面渲染。画布大小和位置任意设置

测试渲染模式

  • 创建一个Button对象:GameObject->UI->Button

  • 创建一个Cube对象

  • 检查、设置以下对象属性

    • Main CameraPosition=(0,1,-10)
    • Canvas::Button(PosX, PosY, PosZ) = (0,0,0)
    • CubePosition=(0,0.5,0)
  • 使用鼠标中间滚轮在场景视图中缩小,直到看到整个画布,中间有一个Button,如图所示:

  • 选择Canvas对象的Inspector面板中Canvas组件

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

    • 设置Render ModeScreen Space - Camera
    • 设置Render CameraMain 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
  • CanvasRender Mode设为World Space,以便改变父对象(画布)的大小
    • 测试结果1:UI元素锚定到父级的中心。该元素保持到中心的固定偏移量
    • 测试结果2:UI元素锚定在父级的右下角,该元素保持到右下角的固定偏移量
    • 测试结果3:左侧角落的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 CameraDirectional Light以外的对象删掉
  • 将如下所示的图片拖入Assets/Texture目录中,作为纹理图像
  • 创建Panel对象:GameObject->UI->Panel
  • Panel下添加Raw Image对象:右键Panel->UI->Raw Image
  • 将前面的纹理图像拖入Raw ImageTextrue插槽中
  • 将场景视图设置为2D,并缩放至能看到整个画布
  • 选择Panel对象
    • Rect Transform组件选择Anchor Presets(middle, center)
    • Rect Tool,将Panel与图片的大小调为一致
    • 添加Mask组件
    • 选择Image组件,选择Source ImageKnob
  • Game视图中,可看到如下效果图:

动画练习

  • 添加Animation编辑视图:Window->Animation->Animation
  • 选择Raw Image
  • 在视图Animation中,点击create按钮,则系统将在该对象上创建动画组件、动画控制器、动画文件,将文件保存为tets1.anim
    • Add Property->Rect Transform->Archored Position->+
  • 选择Scene视图,移动Raw ImagePanel左边
  • 选择Animation视图,(记得先开启录制)在0s位置添加关键帧,将播放位置标线放置在最后
  • 选择Scene视图,移动Raw ImagePanel右边
  • 选择Animation视图,在最后位置添加关键帧
  • 运行动画:

富文本测试

为了显示格式复杂的文字,Unity提供了类似HTML标签,控制字体、字号、颜色。

  • Canvas下添加Text元素
  • Text组件中输入:We are <color=green>green</color> with envy
  • 结果:

简单血条

给动画人物Ethan添加Health Bar

  • 将场景另存为Scene4,将除Main CameraDirectional Light以外的对象删掉
  • Assets Store中下载并导入Standard Assets
  • 添加一个Plane对象:GameObject->3D Object->Plane
  • 将目录Assets/Standard Assets/Characters/ThirdPersonCharacter/Prefabs下的ThirdPersonController预制拖放入场景中,重命名为Ethan
  • 检查以下属性:
    • PlaneTransformPosition=(0,0,0)
    • EthanTransformPosition=(0,0,0)
    • Main CameraTransformPosition=(0,1,-10)
  • Ethan添加画布子对象:右键Ethan->UI->Canvas
  • 添加滑条子对象作为血条:右键Ethan的子对象Canvas->UI->Slider
  • 选择EthanCanvas,在Inspector视图中,
    • 设置Canvas组件Render ModeWorld 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 AreaFill,修改Image组件的Color为红色
  • 选择SliderSlider组件
    • 设置Max Value100
    • 设置Value75
  • 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 CameraDirectional LightPlane

  • 创建一个空对象: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对象,将预制UGUIHealthBarIMGUIHealthBar拖到层级面板中,使之成为ThirdPersonController对象的子对象即可

其他参考资料

潘老师的课程网站 第九章 UI系统
Unity3D学习笔记(四)分别使用IMGUI和UGUI实现血条的预制设计

3D游戏编程与设计作业09相关推荐

  1. 3D游戏编程与设计作业10

    3D游戏编程与设计作业10 环境说明 Unity3D 导航与寻路 Agent 和 Navmesh 练习 Obstacle和Off-Mesh-Link练习 P&D 过河游戏智能帮助实现 状态图 ...

  2. 3D游戏编程与设计作业六

    改进飞碟(Hit UFO)游戏 要求 按 adapter模式 设计图修改飞碟游戏 使它同时支持物理运动与运动学(变换)运动 实现 原项目:3D编程与游戏设计作业五 仅仅对其中的一些类进行改动就能实现. ...

  3. 3D游戏编程与设计作业6-Unity实现打飞碟游戏改进版(Hit UFO)

    改进飞碟(Hit UFO)游戏 游戏内容要求 按adapter模式设计图修改飞碟游戏 使它同时支持物理运动与运动学(交换)运动 编程实践 本次作业直接在上一次打飞碟游戏的基础上增加adapter设计模 ...

  4. 3D游戏编程与设计作业4-Skybox_牧师与魔鬼进阶版

    基本操作演练 下载Fantasy Skybbox FREE,构建自己的游戏场景 直接在上一次作业的Priests and Devils游戏场景中添加天空盒和地形构建场景.首先在Unity Assets ...

  5. 3D游戏编程与设计作业四

    第四次3D编程作业 本次作业源代码链接:点击此处进行跳转 一. 基本操作演练 下载Fantasy Skybox Free,构建自己的游戏场景 场景总览图: 游玩截图: 写一个简单的总结,总结游戏对象的 ...

  6. 3D游戏编程与设计作业三

    第三次3D编程作业 本次作业源代码链接:点击此处进行跳转 1. 简答并用程序验证 游戏对象运动的本质是什么 游戏对象空间属性(坐标.旋转度.大小)的变化 请用三种以上方法,实现物体的抛物线运动 此处我 ...

  7. 3D游戏编程与设计作业2-太阳系-Priests and Devils

    简答题 一.游戏对象运动的本质是什么?   游戏对象的本质是游戏对象每一帧的由空间属性决定的坐标随时间发生改变,其中空间属性包括对象transform属性中的空间位置Position属性.旋转角度Ro ...

  8. 3D游戏编程与设计作业一

    游戏分类与热点探索 使用思维导图描述游戏的分类.(游戏分类方法特别多) 所使用的思维导图绘图工具为mindmaster. 结合手机游戏市场的下载量与排名等数据,结合游戏分类图,描述游戏市场的热点. 华 ...

  9. 3D游戏编程与设计作业4——使用skybox构建游戏场景

    步骤1: 首先下载支持使用Fantacy Skybox FREE 的Unity版本(2021.3) 步骤2:打开unity store, 搜索Fantacy Skybox FREE 并进行下载 步骤3 ...

最新文章

  1. python新建excel表格-python xlwd对excel(表格)写入详解
  2. es index 改名_Elasticsearch Index模块
  3. 基本概率模型和贝叶斯定理
  4. BZOJ3387栅栏行动
  5. 【转载】linux进程及进程控制
  6. 又不能起床python好学吗
  7. CodeForces 164C Machine Programming 费用流
  8. 照顾好自己才能照顾好别人_6种照顾数字外观的方法
  9. 余承东透露华为Mate X发布时间:今年六月上市
  10. C#.Net工作笔记010---c#中的静态扩展方法_可动态给string等_添加共通方法好用
  11. 2017年经历的那些灵异事件
  12. Singleton 与 MonoState 模式
  13. DPDK 实现的不完全笔记
  14. Redis未授权访问缺陷让服务器沦为肉鸡
  15. 360极速浏览器配置Chromedrive
  16. 【OI备忘录】dalao博文收藏夹
  17. win10 安装docker msi主板开启虚拟化
  18. Java知识点总结【6】抽象类和接口
  19. VS2022写Qt代码遇到的问题之 C2504 “xxx”: 未定义基类 (编译源文件
  20. B2B2C分布式微服务电商源码(支持:小程序、公众号、H5、IOS、Android)

热门文章

  1. ESP-C3入门13. SoftAP模式
  2. Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day35】
  3. python pc微信 接收信息_GitHub - ericadver/WechatPCAPI: 微信PC版的API接口,可通过Python调用微信获取好友、群、公众号列表,并收发消息等功能。...
  4. C语言--PTA三天打渔两天晒网问题
  5. 【Flutter应用】Flutter精仿抖音开源
  6. JAVA初学之键盘录入
  7. html搜狐热搜列表仿写,织梦列表页获取热搜排行榜文章
  8. Java编程基础测题(二十道)
  9. 如何windows远程控制mac电脑
  10. SpringBoot:WebSocket实现消息撤回、图片撤回