Unity中实现多层血条

Posted Hello Bug.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity中实现多层血条相关的知识,希望对你有一定的参考价值。

一:效果演示


二:使用

——面板参数设置

HpSlider:Slider组件
TopBar:顶部血条
DownBar:底部血条
LastBarColor:最后一条血条的颜色
T:血量改变时缓动的插值(如果不需要缓动效果则设置为1即可)

——常规使用
创建Slider组件,添加HpBar脚本

using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour

    public HpBar hpBar;

    private void Awake()
    
        List<Color> colorList = new List<Color>()  Color.blue, Color.cyan, Color.green, Color.red ;
        hpBar.SetHpBar(100, colorList);
    

    private void Update()
    
        if (Input.GetKeyDown(KeyCode.A))
        
            hpBar.ChangeValue(6);
        
        if (Input.GetKeyDown(KeyCode.D))
        
            hpBar.ChangeValue(-8);
        
    

——其他使用
CurIndex:当前第几管血
CurHp:当前血量
OnValueChanged:每次血量改变时的回调
OnIndexChanged:每次血条下标改变时的回调


三:代码实现

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

/// <summary>
/// 血条
/// </summary>
public class HpBar : MonoBehaviour

    //血条slider组件
    public Slider hpSlider;
    //顶部血条
    public Image topBar;
    //底部血条
    public Image downBar;

    //最后一个血条颜色
    public Color lastBarColor;
    //缓动差值
    public float t = 0.1f;
    //血条数值变化后
    public Action<int, long> OnValueChanged;
    //血条下标变化后
    public Action<int, long> OnIndexChanged;

    //当前下标(第几管血,降序)
    int m_CurIndex;
    public int CurIndex
    
        get
        
            return m_CurIndex;
        
    
    //当前血量
    long m_CurHp;
    public long CurHp
    
        get
        
            return m_CurHp;
        
    
    //总血量
    long m_TotalHp;
    //每一管血条的血量
    float m_PerValue;
    //血条颜色列表
    List<Color> m_ColorList = new List<Color>();
    //目标值
    float m_TargetValue;
    //目标下标
    int m_TargetIndex;

    /// <summary>
    /// 设置血条
    /// </summary>
    public void SetHpBar(long totalHp, List<Color> colorList, long curHp = -1)
    
        m_ColorList.Clear();
        m_TotalHp = totalHp;
        m_ColorList = colorList;
        m_CurHp = curHp == -1
            ? m_TotalHp
            : curHp;
        InitHpBar();
    

    /// <summary>
    /// 设置血条
    /// </summary>
    public void SetHpBar(long totalHp, List<string> colorList, long curHp = -1)
    
        m_ColorList.Clear();
        m_TotalHp = totalHp;
        foreach (var colorhtml in colorList)
        
            Color color;
            ColorUtility.TryParseHtmlString(colorHtml, out color);
            m_ColorList.Add(color);
        
        m_CurHp = curHp == -1
           ? m_TotalHp
           : curHp;

        InitHpBar();
    

    /// <summary>
    /// 初始化血条
    /// </summary>
    void InitHpBar()
    
        m_CurIndex = m_ColorList.Count;
        m_PerValue = m_TotalHp * 1f / m_ColorList.Count;
        hpSlider.minValue = 0;
        hpSlider.maxValue = m_PerValue;
        hpSlider.value = m_PerValue;

        UpdateIndexAndValue();
        UpdateHpBar(true);
        UpdateColor();
        OnValueChanged?.Invoke(m_CurIndex, m_CurHp);
    

    /// <summary>
    /// 更新血条颜色
    /// </summary>
    void UpdateColor()
    
        topBar.color = m_ColorList[m_CurIndex - 1];
        downBar.color = m_CurIndex - 1 <= 0
            ? lastBarColor
            : m_ColorList[m_CurIndex - 2];
    

    /// <summary>
    /// 更新目标下标和目标值
    /// </summary>
    void UpdateIndexAndValue()
    
        //更新下标
        int targetIndex = 1;
        int indexOffset = m_CurHp % m_PerValue == 0
            ? Mathf.FloorToInt(m_CurHp / m_PerValue) - 1
            : Mathf.FloorToInt(m_CurHp / m_PerValue);
        targetIndex = Mathf.Clamp(targetIndex + indexOffset, 1, m_ColorList.Count);
        m_TargetIndex = targetIndex;

        //更新值
        float targetValue = 0;
        if (m_TargetIndex >= m_ColorList.Count
            && m_CurHp % m_PerValue == 0)
        
            targetValue = m_PerValue;
        
        else
        
            targetValue = m_CurHp % m_PerValue;
        
        m_TargetValue = targetValue;

        OnValueChanged?.Invoke(m_CurIndex, m_CurHp);
    

    /// <summary>
    /// 更新血条
    /// </summary>
    void UpdateHpBar(bool isForce)
    
        if (isForce)
        
            m_CurIndex = m_TargetIndex;
            hpSlider.value = m_TargetValue;
        
        else
        
            if (m_CurIndex == m_TargetIndex)
            
                hpSlider.value = Mathf.Lerp(hpSlider.value, m_TargetValue, t);
                if (Mathf.Abs(hpSlider.value - m_TargetValue) <= 0.01f)
                
                    hpSlider.value = m_TargetValue;
                
            
            else
            
                if (m_CurIndex < m_TargetIndex)
                
                    hpSlider.value = Mathf.Lerp(hpSlider.value, m_PerValue, t);
                    if (Mathf.Abs(hpSlider.value - m_PerValue) <= 0.01f)
                    
                        m_CurIndex++;
                        hpSlider.value = 0;
                        OnIndexUpdate();
                    
                
                else if (m_CurIndex > m_TargetIndex)
                
                    hpSlider.value = Mathf.Lerp(hpSlider.value, 0, t);
                    if (Mathf.Abs(hpSlider.value - 0) <= 0.01f)
                    
                        m_CurIndex--;
                        hpSlider.value = m_PerValue;
                        OnIndexUpdate();
                    
                
            
        
    

    /// <summary>
    /// 改变血条数值
    /// </summary>
    public void ChangeValue(int value)
    
        m_CurHp = (long)Mathf.Clamp(m_CurHp + value, 0, m_TotalHp);

        UpdateIndexAndValue();
    

    private void Update()
    
        UpdateHpBar(false);
    

    /// <summary>
    /// 血条下标变化后
    /// </summary>
    void OnIndexUpdate()
    
        UpdateColor();

        OnIndexChanged?.Invoke(m_CurIndex, m_CurHp);
    

以上是关于Unity中实现多层血条的主要内容,如果未能解决你的问题,请参考以下文章

Unity3D 多层血条特效

Unity3D 多层血条特效

Unity中UGUI人物血条跟随的几种实现方式

Unity3D 血条的渐变效果

Unity3D 血条的渐变效果

在GridControl表格控件中实现多层级主从表数据的展示