【3D游戏编程】9. UI系统

本文详细介绍了在Unity中使用IMGUI和UGUI两种方法实现血条预制设计的过程,包括代码实现、界面布局调整及预制使用方法,对比了两种实现方式的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作业内容

本次作业为五选一,所选题目为血条(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实现

主要参考资料1资料2
首先需要创建一个游戏角色:

  • 从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):

  1. BackGround,实际上是一个GameObject,携带Canvas Renderer这是一个其他渲染器都渲染完毕之后最后使用的渲染器,可以在脚本中调用其含有的参数和方法。
  2. Fill Area,一个空的Rect Transform父物体,下面一个有Canvas Renderer和Image的父物体,主要也是一个区域和图片 默认Slider是个小圆。
  3. 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进行更改(其实就是上面注释的三行代码) :

  1. 首先增加使用UnityEngine.UI
using UnityEngine.UI;
  1. 添加Slider变量
public Slider HealthSlider;
  1. 在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文件夹,直接拖出使用即可。

参考资料

  1. Unity3D学习笔记(四)分别使用IMGUI和UGUI实现血条的预制设计
  2. Unity 3D Lecture Note 8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值