【Unity3d学习】UI系统——简单的血条制作

文章目录

  • 写在前面
  • 实验内容
    • IMGUI制作简单血条
    • UGUI设计血条预制
    • 动态效果展示
    • 两种制作的优缺点
      • IMGUI优缺点分析
      • UGUI优缺点分析
    • 预制使用方法
  • 更新
    • 解决血条暴露行踪问题

写在前面

  • 本次项目较为简单,代码上传到GitHub上:Github传送门
  • 课程实验资料在老师的课程网站上:传送门
  • 实验的视频链接(本次实验演示较简短):传送门

实验内容

实现简单血条预制:

  • 分别使用 IMGUI 和 UGUI 实现
  • 使用 UGUI,血条是游戏对象的一个子元素,任何时候需要面对主摄像机
  • 分析两种实现的优缺点
  • 给出预制的使用方法

步骤分析:
首先IMGUI在之前的实验中也有用到,主要是用来设置开始游戏和结束游戏的界面。实现方法是在onGUI函数中添加相应的控件(Label、Button等),也就是说每次都调用onGUI都会刷新一次所有控件。
而UGUI是课上新接触的UI设计工具。主要设计可以通过鼠标拖拽、设置属性等方式,在二维平面上完成UI设计,即时能够看到效果。换句话说可以不通过代码就能实现一定的UI效果。

分析完两者的一些区别之后就开始动手实现了。

IMGUI制作简单血条

由于IMGUI主要是通过代码来实现UI,所以也没有说需要建立模型什么的,调整位置也是靠代码控制xy坐标来实现。所以直接上代码:

public class IMGUIhealth : MonoBehaviour
{
    public float value;
    private float tmp;
    
    // Start is called before the first frame update
    private void OnGUI()
    {
    	// 加号按钮,点击时增加血量,每次增加十分之一
        if (GUI.Button(new Rect(450, 50, 40, 40), "+"))
        {
            tmp += 10;
            if (tmp > 100)
                tmp = 100;
        }
		// 减号按钮,点击时减少血量,每次减少十分之一
        if (GUI.Button(new Rect(100, 50, 40, 40), "-"))
        {
            tmp -= 10;
            if (tmp < 0)
                tmp = 0;
        }
		// 线性插值,使得变化更平滑
        value = Mathf.Lerp(value, tmp, 0.05f);
	
		// 使用HorizontalScrollbar作为血条主体,利用value来控制血量多少
        GUI.color = Color.red;
        GUI.HorizontalScrollbar(new Rect(200, 50, 200, 20), 0, value, 0, 100);
        
    }
}

代码主要添加了三个控件:两个Button负责加减血量,一个水平滚动条负责显示血量。
Button的用处就不讲了,之前实践过很多次了,对于HorizontalScrollbar来说,是第一次接触,所以看下官方文档:
【Unity3d学习】UI系统——简单的血条制作_第1张图片
大概理解一下各个参数的意思:

Parameter 意义
position 整个滚动条的位置和大小
value 滚动条的那一个滑块的位置
size 滑块大小(长度)
leftValue 最小值
rightValue 最大值
style 滚动条的样式

翻译了一遍,但是对于某些部分还是有点不理解,就拿现成的例子说明以下:
【Unity3d学习】UI系统——简单的血条制作_第2张图片
箭头所指为滑块,可以知道我们滚动移动的时候改变的是滑块的位置。对于不同的网页,滑块的长度会不一样:
【Unity3d学习】UI系统——简单的血条制作_第3张图片
基于这个想法,我们可以利用滑块的长度作为血条现有血量的多少,将滑块的位置固定在0端,也就是最左端(最小值处),改变滑块的长度(0~100)来显示血量的变化。
所以有了以下的这一句代码:

GUI.HorizontalScrollbar(new Rect(200, 50, 200, 20), 0, value, 0, 100);

其中Rect后的第一个数字0,表示滑块的当前位置,0就是最左边。value就是当前血量,也就是对应着滑块长度。
最后将脚本挂载到摄像机上!

显示效果(静态):
【Unity3d学习】UI系统——简单的血条制作_第4张图片
(注:其实有一个控件是HorizontalSlider水平滑动条,但是由于没有滑块的大小,所以显示不出血量的变化,相比之下HorizontalScrollbar更加适合血条的样式)

UGUI设计血条预制

UGUI是为了让设计师能够直接参与UI设计而产生的,所以UGUI有一个设计界面,有所见即所得的方便之处。所以不同于代码编程,用UGUI设计出来会得到一个模型,也就是我们的游戏对象,所以可以将其变为预制,使用的时候直接拖入场景中进行实例化使用。
参考老师课程网站上的教程进行UGUI血条预制:

  1. 首先创建一个Canvas对象作为UGUI控件的一个载体,并且取名为Health.然后在这个载体里面添加一个Slider.对象结构如下:
    【Unity3d学习】UI系统——简单的血条制作_第5张图片
    Slider下的子对象是自动生成的不需要手动添加。

  2. 设置 Canvas 组件 Render Mode 为 World Space
    设置 Rect Transform 组件 (PosX,PosY,Width, Height) 为 (0,2,160,20)
    设置 Rect Transform 组件 Scale (x,y) 为 (0.01,0.01):
    【Unity3d学习】UI系统——简单的血条制作_第6张图片

  3. 由于我们不需要拖动Slider,所以把Handle Slide Area禁用掉,至于Background可以禁可以不禁,不禁的话就可以当空血槽,效果也不错,看个人喜欢。然后更改fill的属性值,在Image的部件中找到color一项,改变它的颜色:
    【Unity3d学习】UI系统——简单的血条制作_第7张图片
    然后在Scene界面点击2D的按钮,可以直观看到效果:
    【Unity3d学习】UI系统——简单的血条制作_第8张图片
    一个绿色的长条就制作完成了。

  4. 改变Slider的属性:
    设置 MaxValue 为 100
    设置 Value 为 75 :
    【Unity3d学习】UI系统——简单的血条制作_第9张图片
    可以看到缺了一部分。如果加上background,会看的更明显:
    【Unity3d学习】UI系统——简单的血条制作_第10张图片

  5. 下面给他添加一个脚本。
    由于它会随着物体转动而转动,所以需要让其时时刻刻都保持面向摄像头,然后自己给他添加了一点颜色改变的逻辑,当血量少到一定程度就会变黄再变红。还做了一个让血条自己变化的一个函数(因为血条量可以通过Slider的Inspetor的slider部件改变,所以这里就没有做一个加减血量的按钮)。

public class HealthBar : MonoBehaviour {

    public Slider slider;
    float factor = 0.1f;
    public bool active = true;
    private int turn = 1;
    private void Start()
    {
    }
	
    void change() {
        if (turn == 1)
            slider.value -= 1f;
        else 
            slider.value += 1f;
        if (slider.value <= 0) {
            slider.value = 0;
            turn = 2;
        }
        if (slider.value >= 100) {
            slider.value = 100;
            turn = 1;
        }
    }
    void Update () {
		this.transform.LookAt (Camera.main.transform.position);
        if (active)
            change();
        Color current = slider.fillRect.transform.GetComponent<Image>().color;
        if (slider.value <= 20) {
            slider.fillRect.transform.GetComponent<Image>().color = Color.Lerp(current, Color.red, factor);
        }
        else if (slider.value <= 70) {
            slider.fillRect.transform.GetComponent<Image>().color = Color.Lerp(current, Color.yellow, factor);
        }
        else {
            slider.fillRect.transform.GetComponent<Image>().color = Color.Lerp(current, Color.green, factor);
        }
	}
}

最后将脚本拖到Heath的画布上面去,将Slider拖入脚本的slider变量中去,完成脚本与Slider的绑定。Active是选择是否让其自动变化。
【Unity3d学习】UI系统——简单的血条制作_第11张图片
将其拖到一个物体Cube上,观察效果:
(看到效果,我们可能会发现,血条的左右是反的?就是会从右边开始增加减少,这时候只需要稍微设置一下slider的方向即可,因为实际上我们创建Slider的时候,他的Z轴是朝向正方向的,也就是说他的正方向恰好的背对着摄像头,这时候我们看到的效果才是正常的,但是如果设置了LookatCamera,那么就会出现了相反的效果,这时候我们可以通过设置他的方向来调整,这个可能实现方法不同效果不太一样,根据实际情况进行调整)
【Unity3d学习】UI系统——简单的血条制作_第12张图片
【Unity3d学习】UI系统——简单的血条制作_第13张图片
拖动Slider的slider部件中的value选项:
【Unity3d学习】UI系统——简单的血条制作_第14张图片
就可以看到血条在变化。

动态效果展示

IMGUI:
【Unity3d学习】UI系统——简单的血条制作_第15张图片
UGUI:
【Unity3d学习】UI系统——简单的血条制作_第16张图片

两种制作的优缺点

IMGUI优缺点分析

优点:

  • 编程实现,符合游戏编程的传统。
  • 避免了 UI 元素保持在屏幕最前端,又有最佳的执行效率,一切控制掌握在程序员手中。对于简单UI的制作十分有好处。
  • 对新手友好,入门容易,同时帮助理解游戏引擎渲染的调用函数
    缺点:
  • 编程实现既是优点,也是缺点,无法直观看到UI布局情况,需要使用代码一点一点更改位置
  • 渲染在屏幕最前端,所以简单的实现只能够用于初始界面、结束界面等的设计,如果想要映射到游戏场景中去,还需要实现更加复杂的大小、位置映射关系,非常麻烦。(IMGUI系统通常不打算用于玩家可能使用并与之交互的普通游戏内用户界面IMGUI系统通常不打算用于玩家可能使用并与之交互的普通游戏内用户界面)

UGUI优缺点分析

优点:

  • 能够让设计师也参与到游戏制作中去,直接利用界面设计UI,所见即所得。
  • UI 元素与游戏场景融为一体的交互,支持复杂的布局,功能更加强大!
  • 面向对象的编程,每个控件都是一个对象,通过对其加减Component或者改变属性可以实现不同的效果。

缺点:

  • 功能强大的同时也意味着它的操作性要更强,许多设计技巧和方法都需要查阅大量资料去学习。
  • 同时性能是个十分值得考虑的问题!

预制使用方法

  1. 新建一个物体(方块什么的,能看到形状的),然后从预制文件夹中找到对应的预制Health,将其拖到一个物体上,使其成为该物体的子对象。(当然也可以直接将预制拖到场景中,单独查看血条的效果)
    【Unity3d学习】UI系统——简单的血条制作_第17张图片
  2. 将Slider拖入脚本的slider变量中去,完成脚本与Slider的绑定(如果还没有赋值的话)。Active是使血量自动循环变化,不喜欢可以关掉。
    【Unity3d学习】UI系统——简单的血条制作_第18张图片
  3. 开始运行游戏!即可看到效果,可以手动改变value的值来显示变化。
    【Unity3d学习】UI系统——简单的血条制作_第19张图片

本次实验到此完成!

更新

提出一点方案建议,没来得及研究实现。
根据参考资料:Faking World Space for monster health bars in Unity

如果你在生产中使用上述血条,足以证明你是入门级别程序员。为了显示血条,每个图片从 pixel 单位映射到 world space,再投影到摄像机空间,在变成屏幕空间(pixel 单位)这需要多少算力?
因此,能用 Srceen Space 解决的问题绝不用 World Space, 能用 Overlay 解决问题绝不用 Camera!

由于使用World Space会降低性能,这个例子中是用到Canvas 组件 Render Mode 为Screen Space - Overlay来实现的。所以会需要一个从worldSpace到屏幕的映射关系,主要有z轴(摄像机朝向)对应深度信息,xy对应xy
【Unity3d学习】UI系统——简单的血条制作_第20张图片
【Unity3d学习】UI系统——简单的血条制作_第21张图片
完成一个从三维控件到屏幕平面坐标的映射。

解决血条暴露行踪问题

在该例子中也给出了明确的方案:
【Unity3d学习】UI系统——简单的血条制作_第22张图片
可以根据这个例子来学习UGUI更多知识!再放一遍链接:
Faking World Space for monster health bars in Unity

你可能感兴趣的:(Unity3d学习)