关于DNF多层血条的实现

本篇博客主要简述类似于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工具

下篇写出多段血条的实现方式,希望大家多多支持。

喜欢我,关注我,我是壹叶成名!

部分资源来源于网络,如有侵权,请联系我删除。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铸梦xy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值