Unity 3D 血条制作

要求:

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

思路:

​ 由于之前一直有用IMGUI,还算熟悉,想法就是使用一个类似长方形的容器,实现血条效果。至于UGUI,按照老师上课所讲的,使用Slider,通过调整,实现。

实现:

IMGUI

​ 新建一个Cube,作为游戏对象,或者空对象也可以,重点不在此处(不过还是太随便了些。。)。

​ 新建脚本 IMGUI.cs ,初步想法:设置一根血条,两个按键,一个为攻击,即掉血,另一个为大治疗术,一下全加满。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class IMGUI : MonoBehaviour {
private Rect blood;//血条
private float value;//代表当前血量
// Use this for initialization
void Start () {
value = 100f;
blood = new Rect(250, 100, 150, 20);
}

// Update is called once per frame
void OnGUI()
{
if (GUI.Button(new Rect(20, 20, 80, 40), "Attack"))
{
if (value >= 10)
{
value -= 10;
}
else
{
value = 0;

}
}
if (GUI.Button(new Rect(20, 130, 80, 40), "Revive"))
{
value = 100;
}
GUI.HorizontalScrollbar(blood, 0.0f, value, 0.0f, 100f);
}
}

​ 本次难点还是在于如何实现血条的效果,查阅资料之后,采用了 GUI.HorizontalScrollbar() , 即滚动条,具体参数如下:

public static float HorizontalScrollbar(Rect position, float value, float size, float leftValue, float rightValue);

​ 其中第一个参数是一个长方形,第二个参数官方的说明是:

The position between min and max.

​ 我试了多次之后,发现这个是控制血条缩减的方向的,例如现在是0,就是从右往左缩减,如果是最大值100,则是从左往右缩减。若是一个中间值,则先从左往右,然后缩减到相应比例时,再从右往左缩减。

​ 第三个是当前的血量,即一个区间内的值;第四和第五分别是区间的最小值和最大值。其实最后也可以加个 GUIStyle 的参数来着,我添加了之后不知怎么的总是显示不出来,然后还报了一堆警告,就没用了。

IMGUI效果图

使用说明:预制已给出,为Prefabs/IMGUI,将其拖入场景中,点击运行即可。初始血量为100,点击Attack掉10点血,点击Revive复活,即血量全满。

UGUI

​ 与 IMGUI 类似的是,首先新建一个Cube(看心情,是个对象就行),在Cube下新建子对象Canvas,之后再在Canvas下新建一个Slider,两个Button,控制攻击和复活,具体目录结构如下:

层次结构

​ 其中,UGUI是Cube的名称,Slider目录下原本还有 Handle Slide Area ,此处不用,删去,否则会遮挡血条效果。

​ 设置Slider的 Rect Transform 中的 WidthHeight 分别为80和20,为血条的大小,然后设置 Scale 下的X和Y分别为0.02,0.01,控制血条在X和Y轴上的比例因子,可个性化设置。

​ 其次设置血条颜色,Slider–>Fill Area–>Fill–>Image–>Color,挑选自己喜欢的颜色即可。

​ 最后回到Slider的Inspector界面,如下设置:

设置

​ 其中 Direction 是血条缩减方向, Min Value 是血量最小值, Max Value 是最大值, Value 是当前血量,通过拖动滑条可看到血量变化效果。此处需要说明的是,我刚开始设置的时候发现血量最多也到不了最右边,即看起来永远也不会满的样子,之后通过设置 Fill Area –> Fill 中的Rect Transform属性解决,将其中所有数值设为0即可。其实也可以通过不断更改数值,发现各个属性的作用的,这个可以自己摸索,也是蛮有意思的。

​ 接下来开始写代码,要求中有要血条时刻面对摄像机,所以代码如下,将其绑定到Canvas下即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Follow : MonoBehaviour {

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
this.transform.rotation = Camera.main.transform.rotation;
}
}

​ 然后设置 Canvas–>Render Mode–>World Space , 然后将主摄像机拖入下面的 Event Camera 。即是使UI采用世界模式。

​ 由于采用世界模式,所以继续编写血条坐标变化的代码,将其绑定到Slider下即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UGUI : MonoBehaviour {
private RectTransform rectTransform;
// Use this for initialization
void Start () {
rectTransform = this.GetComponent<RectTransform>();;
Camera.main.transform.position = new Vector3(0, 0, -5);
Vector3 postion = Camera.main.ScreenToWorldPoint(this.transform.position);
rectTransform.position = postion + new Vector3(0, 1, 5);
}
}

​ 之后继续设置两个Button,大小和位置通过调整,适应即可,颜色之类也可自定义,具体以攻击按钮为例:

按钮属性

​ 最后就是脚本的书写了,Button有个 On Click 属性,通过查询官方手册后得知了用法,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Attack : MonoBehaviour {
public Slider slider;
// Use this for initialization
void Start()
{
Button btn = this.GetComponent<Button>();
btn.onClick.AddListener(Click);
}
public void Click()
{
if(slider.value >= 10)
{
slider.value -= 10;
}
else
{
slider.value = 0;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Revive : MonoBehaviour {
public Slider slider;
// Use this for initialization
void Start () {
Button btn = this.GetComponent<Button>();
btn.onClick.AddListener(Click);
}

public void Click()
{
slider.value = 100;
}
}

​ 将这两个脚本绑定到相应的Button上,此处的难点是刚开始时无法获得Slider的value,之后查找官方手册和资料,找到了这种解决方法,提供一个公有的接口,将其在外部设置为血条Slider属性即可,然后就解决了。

效果图:

UGUI效果图

使用说明:左边为攻击按钮,右边为复活按钮,操作规则与IMGUI相同。预制为Prefabs/UGUI,拖入场景之中即可使用。

分析:

IMGUI:制作步骤较为简单,但是也很简陋,效果明显不如UGUI(也有可能是我水平有限)。其次,血条位置不能够随着对象移动而变化,因为长方形的坐标是相对于屏幕的,所以不会变化。

UGUI:效果明显要好很多,血条也可以随着物体移动。但是制作较为复杂,容易出错,需要仔细阅读官方文档。由于上课老师课件讲过UGUI血条在World Space下的弊端,就是血条会暴露对象的位置,我本来是打算采用ScreenSpace-Overlay模式的,然后最后没有做出来,只能先这样子,之后再钻研下吧,对UI还是了解不够。

资源传送门:点这里

演示视频:看看吧

分享到 评论