1.Controller.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static LifeBar;
public class Controller : MonoBehaviour
{
private LifeBar _bar;
// Start is called before the first frame update
void Start()
{
Canvas canvas = FindObjectOfType<Canvas>();
if (canvas == null)
{
Debug.LogError("场景中没有Canvas组件");
return;
}
//生成血条物体
SpwanLifeBar(canvas);
}
//加载血条资源
private void SpwanLifeBar(Canvas canvas)
{
//加载血条预制体
GameObject prefab = Resources.Load<GameObject>("LifeBar");
//实例化生成血条,添加lifebar组件
_bar = Instantiate(prefab, canvas.transform).AddComponent<LifeBar>();
List<LifeBarData> data= new List<LifeBarData>();
data.Add(new LifeBarData(null, Color.green));
data.Add(new LifeBarData(null,Color.red));
data.Add(new LifeBarData(null, Color.yellow));
//初始化lifebar脚本
_bar.Init(transform,350,data);
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.A))
{
Move(Vector3.right);
}
if (Input.GetKey(KeyCode.D))
{
Move(Vector3.left);
}
if (Input.GetKey(KeyCode.S))
{
Move(Vector3.down);
}
if (Input.GetKey(KeyCode.W))
{
Move(Vector3.up);
}
if (Input.GetMouseButtonDown(0))
{
_bar.ChangeLife(-50);
}
if (Input.GetMouseButtonDown(1))
{
_bar.ChangeLife(50);
}
}
private void Move(Vector3 direction)
{
transform.Translate(direction * Time.deltaTime * 5);
}
}
2.LifeBar.cs
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
//lifebar是管理类lifebaritem是子类
public class LifeBar : MonoBehaviour
{
//定义人物的transform组件
private Transform _target;
//定义人物包围盒的最高点
private Vector3 _offSet;
//定义血条数据的列表
private List<LifeBarData> _data;
//定义血条的两个子物体
private LifeBarItem _nextBar;
private LifeBarItem _currentBar;
//定义单位血量的宽度
private float _unitLifeScale;
//定义当前血条id
private int _currentIndex;
//初始化
//target人物的位置
//life总血量
public void Init(Transform target,int lifeMax,List<LifeBarData> data)
{
_currentIndex = 0;
_target = target;
//获得人物最高点
_offSet= GetOffSet(target);
//获得血条数据
_data = data;
//给子物体添加lifebaritem脚本控制子物体
_nextBar = transform.Find("NextBar").AddComponent<LifeBarItem>();
_currentBar = transform.Find("CurrentBar").AddComponent<LifeBarItem>();
//定义rect获得lifebar的宽度
_nextBar.Init();
_currentBar.Init();
RectTransform rect = GetComponent<RectTransform>();
//计算单位血量的宽度
_unitLifeScale = rect.rect.width * data.Count / lifeMax;
SetBarData(_currentIndex, data);
}
//获得人物包围盒的最高点
public Vector3 GetOffSet(Transform target)
{
Renderer renderer = target.GetComponent<MeshRenderer>();
if (renderer == null) return Vector3.zero;
return renderer.bounds.max.y * Vector3.up;
}
private void Update()
{
if (_target == null) return;
//血条的位置
transform.position= Camera.main.WorldToScreenPoint(_target.position+_offSet);
}
//改变血量的方法
public void ChangeLife(float value)
{
//不管加血还是减血,width对应着新的血条的亮,width=0代表次加血减血不会溢出到下一个血条
float width= _currentBar.ChangeLife(value * _unitLifeScale);
//减血
if (width<0&&ChangeIndex(1))
{
Exchange();
_currentBar.transform.SetAsLastSibling();
_nextBar.ResetToWidth();
SetBarData(_currentIndex,_data);
//此时width/_unitLifeScale的结果不在对应value,因为width对应的是新的血条的宽度,所以要这样乘一下,不能直接用value
ChangeLife(width / _unitLifeScale);
}
//加血
if(width>0&&ChangeIndex(-1))
{
Exchange();
_currentBar.transform.SetAsLastSibling();
_currentBar.ResetToZero();
SetBarData(_currentIndex, _data);
ChangeLife(width/_unitLifeScale);
}
}
private void Exchange()
{
var temp = _nextBar;
_nextBar = _currentBar;
_currentBar= temp;
}
//1代表减血 -1代表加血
private bool ChangeIndex(int symbol)
{
int index = _currentIndex + symbol;
if ( index>=0&&index<_data.Count)
{
_currentIndex = index;
return true;
}
return false;
}
//初始化血条数据
private void SetBarData(int index,List<LifeBarData> data)
{
if (index < 0 || index >= data.Count) return;
_currentBar.SetData(data[index]);
//如果下一块血条是最后一条
if (index+1>=data.Count)
{
_nextBar.SetData(new LifeBarData(null,Color.white));
}
else
{
_nextBar.SetData(data[index + 1]);
}
}
//定义一个血条的数据结构
public struct LifeBarData
{
public Sprite BarSprite;
public Color BarMainColor;
//血条的构造函数
public LifeBarData (Sprite sprite,Color color)
{
BarSprite = sprite;
BarMainColor = color;
}
}
}
3.LifeBarItem.cs
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
using static LifeBar;
//lifebar是管理类lifebaritem是子类
public class LifeBarItem : MonoBehaviour
{
private float defaultWidth;
//定义血条滑动特效
private LifeBarItem _child;
//定义私有字段获取image类型的对象
//定义公共属性获得image组件并且赋值给_image
private Image _image;
public Image Image
{
get
{
if ( _image == null )
_image = GetComponent<Image>();
return _image;
}
}
private RectTransform _rect;
public RectTransform Rect
{
get
{
if (_rect == null )
{
_rect = GetComponent<RectTransform>();
}
return _rect;
}
}
public void Init()
{
if (transform.Find("AdditionBar")!=null)
{
_child=transform.Find("AdditionBar").gameObject.AddComponent<LifeBarItem>();
defaultWidth = Rect.rect.width;
}
}
//定义接受数据的方法
public void SetData(LifeBarData data)
{
Image.color = data.BarMainColor;
if (data.BarSprite!=null)
{
Image.sprite = data.BarSprite;
}
if (_child != null)
{
_child.SetData(data);
//Debug.Log("111");
}
}
//改变血量
public float ChangeLife(float value)
{
if (_child != null)
{
_child.DOKill();
_child.Image.color=Image.color;
_child.Rect.sizeDelta = Rect.sizeDelta;
//Oncomplete是回调操作,回调执行匿名函数
_child.Image.DOFade(0, 0.5f).OnComplete(()=>_child.ChangeLife(value));
Debug.Log("111");
}
//这个value是value*单位值像素量的
Rect.sizeDelta += Vector2.right * value;
return GetOutOfRange();
}
private float GetOutOfRange()
{
float offset = 0;
if (Rect.rect.width<0)
{
offset= Rect.rect.width;
ResetToZero();
}
else if(Rect.rect.width>defaultWidth)
{
offset = Rect.rect.width - defaultWidth;
ResetToWidth();
}
return offset;
}
public void ResetToZero()
{
Rect.sizeDelta = Vector2.zero;
}
public void ResetToWidth()
{
Rect.sizeDelta = Vector2.right * defaultWidth;
}
}