血条的实现

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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值