Unity3d——UI(血条制作)

血条(Health Bar)制作。具体要求如下

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

IMGUI
效果图:
(血条红色不是很明显,为了显示IMGUI,因此把整个界面都截图了)
这里写图片描述

The “Immediate Mode” GUI system (also known as IMGUI) is an entirely separate feature to Unity’s main GameObject-based UI System. IMGUI is a code-driven GUI system, and is mainly intended as a tool for programmers. It is driven by calls to the OnGUI function on any script which implements it.

简单来说就是利用代码绘各种控件,创建每种控件的方法都是雷同的。以前写井字棋的时候用过,现在上手弄个血条并不困难。选择用scrollabr

GUI.HorizontalScrollbar(new Rect(20, 20, 200, 20), 0.0f, bloodValue,0.0f, 1.0f, GUI.skin.GetStyle("HorizontalScrollbar"));

主要是利用Mathf.Lerp,Lerp(min,max ,c);
一个“控制进度”的函数,可以看unity中mathf.Lerp的运用,有很多应用介绍。

 bloodValue = Mathf.Lerp(bloodValue, tmpValue, 0.01f);

当按下加血按钮的时候,bloodValue值从0向1增加;反之向0减少。
完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Blood : MonoBehaviour {

    public float bloodValue;

    private float tmpValue;

    void Start()
    {
        tmpValue = 0.0f;
        bloodValue = 0.0f;
    }

    void OnGUI()
    {    
        //点击加血
        if (GUI.Button(new Rect(250, 20, 40, 20), "+"))
        {
            tmpValue = 1.0f;
        }

        //点击减血
        if (GUI.Button(new Rect(250, 50, 40, 20), "-"))
        {
            tmpValue = 0.0f;
        }

        bloodValue = Mathf.Lerp(bloodValue, tmpValue, 0.01f);

        GUI.color = Color.red; //血条,设置为红色
        GUI.HorizontalScrollbar(new Rect(20, 20, 200, 20), 0.0f, bloodValue,0.0f, 1.0f, GUI.skin.GetStyle("HorizontalScrollbar"));

    }

}

UGUI
游戏对象选择新建一个Cube,然后血条选择用Slider实现,并且是Cube的子对象。整个架构如图:
这里写图片描述
设置上还蛮简单的,把Slider的Max Value值调成100,可以通过拖动Value来改变Slider的值看效果。Fill Area调成红色就可以有血量增加减少的效果,
这里写图片描述
这里写图片描述
遇到一个小问题,由于滑块的存在,即使Value达到最大值,血条也会显示没有填满,如图
这里写图片描述
直接删掉滑块没有用,还是会有空缺位置。想到一个粗暴的方法,直接把Background取消了,这样就看不出来所谓的填满是到哪里,效果还不错。查了一下,也有人遇到过用UGUI Slider做血条时遇到的一个小问题,他的方法是

将Fill Area及其孩子Fill的Left和Right都调成0才行。这样问题就解决了。
Left是指UI控件的左边缘相对于Anchors Min X的距离,Right是右边缘相对于Anchors Max X的距离。

这样也可以。
需要注意的是在对Cube新建子对象的时候,Canvas的设置。直接新建Canvas,会看到一个充满整个游戏界面的画布,需要调整一下。
这里写图片描述
相应的,在Canvas下创建一个Slider的时候,也需要相应调整Slider的缩放比例。这个摸索一下就差不多能找到适合的位置和大小。我设置的Scale是0.02,0.01,1。根据Cube的位置调整一下Position就可以了。

写了一个简单的控制Cube移动旋转的脚本,现在能够实现的效果是血条跟随Cube移动而移动,但是也会跟着Cube旋转,这样就没有达到要求的一直面对主摄像机的效果。

要实现一直面对主摄像机可以有很简单的实现:

//挂在Canvas上即可
    void Update () {
        transform.LookAt(Camera.main.transform);
    }

类似的,还可以

void Update() {
transform.rotation = Camera.main.transform.rotation;
}

如果不要求Canvas作为Cube的子对象,其实也可以实现跟随效果(坐标上移动),这样Cube旋转的时候,血条是不会转动的。通过这种方式实现可以参考Unity中UGUI人物血条跟随的几种实现方式

最终的效果是可以通过WASD控制Cube移动,QE控制Cube旋转,血条跟随Cube移动,但是Cube旋转时血条一直正对玩家。

没有专门实现血条增加减少的效果,因为查了一下没有看到直接通过在Slidershan上挂载脚本控制Value值的操作,一般是Cube(游戏对象)的某种事件影响,Value值变化,这次作业重点在UI,就没有实现。研究了一下其实可以通过On Value Change来实现事件触发效果,比如Value到达某个值Cube移动之类的,机制类似之前的发布者订阅者模式的通信效果,也就没有重复。


二者比较
IMGUI:优点是实现简单,比如绘制一个控件,只需要GUI.Lable()、GUI.Button()这样即可,不需要使用UI组件,很容易上手。缺点是不利于布局,在协调对象之间的位置关系的时候会很麻烦,这样维护起来也会很困难。调用OnGUI,每一帧都需要重算布局重新渲染,性能低下。

UGUI:优点是可视化,所见即所得。UGUI的控件是以“游戏对象”的形式存在与游戏场景中,这样直观易于使用,直接可以在Scene视图中编辑大小、位置、旋转角度、缩放等等,不需要手动写任何代码。据说效率比较高,“提供了一个经过优化的解决方案,使得开发者添加到游戏中的UI能够快速的被GPU执行(绘制)”直观的缺点是上手比较困难,学习成本比较高,提供强大功能的同时意味着需要花更多的时间了解这些功能的使用。其他的如CPU、GPU和内存方面的比较深层的问题,没有太多了解。
Unity GUI(uGUI)使用心得与性能总结中有提到一些关于UGUI性能的问题。

猜你喜欢

转载自blog.csdn.net/qq_32335095/article/details/80524942