本篇博客主要简述类似于DNF的多层血条的实现方法,
图一是伤害过高,造成的流血效果。
图二是伤害比较低,造成的掉血效果。
之前自己写了一种通过三个Slider的多层血条,实现方式就是控制血条的背景和前景颜色,显然目标
也是达到了,但总归还是有点麻烦,后来闲暇之余又在网上浏览了些帖子,总结了下经验,通过控制
Image的Fill Amount也是实现了多层血条的效果,下面贴出实现方式。
血条由四层图片构成:
BackGrandImage 最底层黑色空血背景,
NextImage 下一个血条的图片,
MiddleImage 掉血时的过度血条,
CurrentImage 现在的血条。
记住要把ImageType的Filled 横向,类似于下面这样
UI的设置就这么多了,下面附上源码:
///------------------
/// 壹叶成名
///------------------
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class BossBloodstrip : MonoBehaviour
{
//如果只有一条血,那么一条血就是所有的血量,如果有多条血,那么一条血就设定为一个固定值
public Image currentBar; //当前血条
public Image middleBar; //过渡血条
public Image nextBar; //下一血条
public Text countText; //剩下的血条数text
private int count; //剩下的血条数(不包括当前血量)
private float nowBlood; //在一条血中的当前血量,如:100/1000则为100
private float oneBarBlood = 10000f; //一条血的容量,如:100/1000则为1000
private int colorIndex = 0;
public Color[] colors; //血条的颜色,注意Alpha值,默认为0
private float slowSpeed = 0.1f; //受到重伤时( >oneBarBlood)或者处于加血状态,当前血条的流动速度
private float quickSpeed = 1f; //受到轻伤时( <oneBarBlood),当前血条的流动速度
private float speed; //当前血条采用的速度
private float middleBarSpeed = 0.1f; //过渡血条的流动速度
private float nowTargetValue; //当前血条移动的目标点
private float middleTargetValue; //过渡血条移动的目标点
private bool isBloodMove = false; //控制血条的移动
void Update()
{
MoveNowBar(); //当前血条的流动
MoveMiddleBar(); //过渡血条的流动
if (Input.GetMouseButtonDown(0))
{
ChangeBlood(-3000);
}
else if (Input.GetMouseButtonDown(1))
{
ChangeBlood(-15000);
}
}
private void Awake()
{
}
private void Start()
{
//初始每一管血条的颜色
colors = new Color[] { new Color(0, 1, 1, 1), new Color(0, 1, 0, 1), new Color(0, 0, 1, 1),new Color(1, 1, 0, 1) };
InitBlood(2000000);
}
/// <summary>
/// 传入总血量,初始化血条
/// </summary>
/// <param name="number"></param>
public void InitBlood(float number)
{
count = (int)(number / oneBarBlood);//剩下的血条数
nowBlood = number % oneBarBlood;//最后一条血的当前血量
if (nowBlood == 0) //如果最后一条血的血量刚好充满剩余血条数减一
{
nowBlood = oneBarBlood;
count--;
}
colorIndex = count % colors.Length;
currentBar.color = colors[colorIndex];
currentBar.fillAmount = nowBlood / oneBarBlood;
if (count != 0)
{
int nextColorIndex = (colorIndex - 1 + colors.Length) % colors.Length;
nextBar.color = colors[nextColorIndex];
nextBar.gameObject.SetActive(true);
}
else
{
nextBar.gameObject.SetActive(false);
}
middleBar.gameObject.SetActive(false);
countText.text = count + "";
}
/// <summary>
/// 血量变化,并根据伤害判断是否使用过渡血条
/// </summary>
/// <param name="number"></param>
public void ChangeBlood(float number)
{
nowBlood += number;
nowTargetValue = nowBlood / oneBarBlood;
isBloodMove = true;
if ((number < 0) && (Mathf.Abs(number) <= oneBarBlood))//处于受伤状态并且伤害量较低时
{
speed = quickSpeed;
middleBar.gameObject.SetActive(true);
middleBar.transform.SetSiblingIndex(nextBar.transform.GetSiblingIndex() + 1);
middleBar.fillAmount = currentBar.fillAmount;
middleTargetValue = nowTargetValue;
}
else//处于受伤状态并且伤害量较大时,或者处于加血状态
{
speed = slowSpeed;
middleBar.gameObject.SetActive(false);
}
}
/// <summary>
/// 普通血条的流动
/// </summary>
void MoveNowBar()
{
if (!isBloodMove) return;
currentBar.fillAmount = Mathf.Lerp(currentBar.fillAmount, nowTargetValue, speed);
if (Mathf.Abs(currentBar.fillAmount - nowTargetValue) <= 0.01f)//到达目标点
isBloodMove = false;
if (count == 0)
nextBar.gameObject.SetActive(false);
else
nextBar.gameObject.SetActive(true);
if (currentBar.fillAmount >= nowTargetValue)
SubBlood();
else
AddBlood();
}
/// <summary>
/// 过渡血条的流动
/// </summary>
void MoveMiddleBar()
{
//受到轻伤时( <oneBarBlood),才会出现过渡血条
if (speed == quickSpeed)
{
middleBar.fillAmount = Mathf.Lerp(middleBar.fillAmount, middleTargetValue, middleBarSpeed);
if (Mathf.Abs(middleBar.fillAmount - 0) < 0.01f)
{
middleBar.transform.SetSiblingIndex(nextBar.transform.GetSiblingIndex() + 1);
middleBar.fillAmount = 1;
middleTargetValue++;
}
}
}
void AddBlood()
{
float subValue = Mathf.Abs(currentBar.fillAmount - 1);
if (subValue <= 0.0f)//到达1
{
count++;
countText.text = count.ToString();
currentBar.fillAmount = 0;
nowTargetValue -= 1;
nowBlood -= oneBarBlood;
nextBar.color = colors[colorIndex];
colorIndex++;
colorIndex %= colors.Length;
currentBar.color = colors[colorIndex];
}
}
void SubBlood()
{
float subValue = Mathf.Abs(currentBar.fillAmount - 0);
if (subValue <= 0.0f)//到达0
{
//当前血条已经流动完,将过渡血条放置最前
middleBar.transform.SetSiblingIndex(nextBar.transform.GetSiblingIndex() + 2);
if (count <= 0)
{
middleBar.gameObject.SetActive(false);
Destroy(this);
return;
};
count--;
countText.text = count.ToString();
currentBar.fillAmount = 1;
nowTargetValue += 1;
nowBlood += oneBarBlood;
colorIndex--;
colorIndex += colors.Length;
colorIndex %= colors.Length;
if (count ==0)
{
currentBar.color = Color.red;//当血量为最后一条时 设置血条为红色
}
else
{
currentBar.color = colors[colorIndex];//根据自设颜色进替换
}
int nextColorIndex = colorIndex - 1 + colors.Length;
nextColorIndex %= colors.Length;
if (count == 1)
{
nextBar.color = Color.red; //设置最后一个血条的显示为红色
}
else
{
nextBar.color = colors[nextColorIndex];//根据自设颜色进替换
}
}
}
}
血条的层数是根据最大血量进行自动生成的,颜色可以在Start里设定,也可以在数组里选自己喜欢的颜色。
附件:
多层血条Demo工具
下篇写出多段血条的实现方式,希望大家多多支持。
喜欢我,关注我,我是壹叶成名!
部分资源来源于网络,如有侵权,请联系我删除。