作业内容
本次作业为五选一,所选题目为血条(Healthy Bar)预制设计,具体要求如下:
- 分别使用 IMGUI 和 UGUI 实现
- 使用 UGUI,血条是游戏对象的一个子元素,任何时候需要面对主摄像机
- 分析两种实现的优缺点
- 给出预制的使用方法
演示视频:bilibili
项目地址:Github
设计实现
IMGUI实现
IMGUI(Immediate Mode
GUI,及时模式图形界面)是代码驱动的UI,没有图形化设计界面,只能在OnGUI()阶段用GUI系列的类绘制UI元素,且设计的UI元素只能浮在游戏界面。
主要参考:参考资料1。
新增一个空对象,命名为HealthBarIMGUI,新建脚本HealthyBar_IMGUI.cs,加入如下代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//using UnityEngine.UI;
public class HealthyBar_IMGUI : MonoBehaviour
{
public float curHP;//当前血量
public float lerpHP;//变化后的目标血量
public float maxHP;//最大血量
public Rect HealthBar;//血条框
public Rect HealthUp;//加血按钮
public Rect HealthDown;//减血按钮
//public Slider HealthSlider;
// Start is called before the first frame update
void Start()
{ //相关变量初始化
//血量相关值初始化
curHP = 0.5f;//初始值为半管血
lerpHP = 0.5f;
maxHP = 1.0f;
//条框,按钮位置初始化
HealthBar = new Rect(25,25,300,50);
HealthUp = new Rect(45,50,50,30);
HealthDown = new Rect(250,50,50,30);
}
// Update is called once per frame
void OnGUI()
{
if (GUI.Button(HealthUp, "加血"))
{
lerpHP = lerpHP + 0.1f > maxHP ? maxHP : lerpHP + 0.1f;
}
if (GUI.Button(HealthDown, "减血"))
{
lerpHP = lerpHP - 0.1f < 0.0f ? 0.0f : lerpHP -0.1f;
}
//插值计算health值,实现血条平滑变化
curHP = Mathf.Lerp(curHP,lerpHP,0.05f);
//用水平滚动条的宽度作为血条的显示值
GUI.HorizontalScrollbar(HealthBar,0.0f,curHP,0.0f,maxHP);
// HealthSlider.value = curHP;
}
}
将脚本挂载到HealthBarIMGUI上,点击运行,即可有如下效果:
UGUI实现
- 从Assert Store中下载人物资源Stansard Assets,导入。
- 在层次视图Hierarhy,Create -> 3D Object -> Plane,添加 Plane 对象
- 资源视图Assets展开 Standard Assets :: Charactors :: ThirdPersonCharater :: Prefabs
- 将 ThirdPersonController 预制拖入场景,作为Plane的子对象,改名为 Arthur。
- 调整Arthur的位置使其面对相机并在相机视野中央。位置参数与各自的操作有关,贴出来也没有太大意义。如果没有对相机进行什么特殊调整的话,将Arthur的Transform中的RotationY改为180就能将角色调整至面向相机。
现在需要为角色添加血条: - 选中Arthur,鼠标右键(上下文菜单)-> UI -> Canvas,添加画布子对象。
- 点击 Canvas,在 Inspector 视图中
- 设置Canvas 组件 Render Mode 为 World Space。
- 设置 Rect Transform 组件的 (PosX, PosY, Width, Height) 为 (0,2,160,20)。
- 设置 Rect Transform 组件的 Scale(x, y)为 (0.01,0.01)。
- 层次视图中选中Canvas,鼠标右键(上下文菜单)-> UI -> Slider,添加血条子对象。
- 层次视图中展开 Slider:
- 选择 Background,修改修改 Image 组件的 Color 为 红色(表示损失的血量)。
- 选择 Fill Area 的 Fill,修改 Image 组件的 Color 为 绿色(表示剩余的血量)。
- 选择 Handle Slider Area,修改 Image 组件的 Color 为 绿色。
关于三个元素的解释(摘自参考资料2):
- BackGround,实际上是一个GameObject,携带Canvas Renderer这是一个其他渲染器都渲染完毕之后最后使用的渲染器,可以在脚本中调用其含有的参数和方法。
- Fill Area,一个空的Rect Transform父物体,下面一个有Canvas Renderer和Image的父物体,主要也是一个区域和图片 默认Slider是个小圆。
- Handler Slider Area,类似Fill Area,默认Slider是个大圆,可以移动位置看其中的fillArea,可以看出其将图片拉长了,这就应该是所谓的填充。如果把Handle删除,会发现进度条永远走不到最大,这是由于Fill Area中的Fill的大小比背景图上的条小,最后一段到达不了,而Handle存在时是一个大圆可以覆盖到最远端。
- 层次视图中选中Slider,在 Inspector 视图
- 设置Slider 组件的 MaxValue 为 1。
- 设置 Rect Transform 组件的Rotation = (0,180,0)
- 调整Canvas和Slider的大小位置使得血条在角色头顶上方适当位置。
如果此时运行程序,会发现用方向键控制人无时,血条会跟着人物旋转,所以需要给Carvas添加脚本LookAtCamera.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookAtCamera : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
this.transform.LookAt(Camera.main.transform.position);
}
}
此时血条就会一直面向主摄像机(但是由于摄像机是不动的,在角色运动的过程中,角色与摄像机的角度就改变了,血条与任务的相对位置看起来也有所改变)。
然而此时的人物血条与IMGUI血条没有联系,按动加血减血按钮并不能让人物血条变化。所以要对HealthyBar_IMGUI.cs进行更改(其实就是上面注释的三行代码) :
- 首先增加使用UnityEngine.UI
using UnityEngine.UI;
- 添加Slider变量
public Slider HealthSlider;
- 在OnGUI中将当前血量的值传给Slider
HealthSlider.value = curHP;
进行如上更改后,还需要最后一步:把Canvas的子对象Slider拖入HealthBarIMGUI对象的IMGUI.cs组件中的HealthSlider属性。
此时可新建文件夹Resources/Prefabs,将空物体HealthBarIMGUI拖入Plane作为其子对象,并将Plane拖入Prefabs文件夹,作为预制。
两种实现的优缺点
IMGUI
优点:
- IMGUI 的存在符合游戏编程的传统
- 入门容易,帮助新手理解引擎的游戏循环
- 在修改模型,渲染模型这样的经典游戏循环编程模式中,在渲染阶段之后,绘制 UI 界面无可挑剔
缺点:
- 传统代码驱动的 UI 面临效率低下,难以调试
- 不利于布局,在协调对象之间的位置关系的时候会很麻烦
- 调用OnGUI,每一帧都需要重算布局重新渲染,性能低下
UGUI
优点:
- 所见即所得(WYSIWYG)设计工具,设计师也能参与程序开发
- 支持多模式、多摄像机渲染
- UI 元素与游戏场景融为一体的交互
- 面向对象的编程
缺点:
- 上手相对困难,学习成本较高
预制的使用方法
已将所有必要元素及其设置修改完毕并且作为预制拖入了Prefabs文件夹,直接拖出使用即可。