一:效果演示
二:使用
——面板参数设置
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);
}
}
|