Unity3D 多层血条特效

Posted 穿迷彩服的鲨鱼

tags:

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

提示:素材来源网络,侵权必删

Unity3D 多层血条特效


效果图

鼠标左右键控制其血条增减


提示:以下是本篇文章正文内容,下面案例可供参考

一、准备项目工程

1.创建项目,准备一个物体如图

提示:Hierarchy面板需准备如下

2.制作血条预制体,把此预制体放在Resources下

提示:创建四个Image按此排列

二、效果代码

1.创建Controller脚本挂在Hierarchy下创建的物体上

代码如下(示例):

using System.Collections.Generic;
using UnityEngine;

namespace HKZ

    /// <summary>
    /// 测试代码
    /// </summary>
    public class Controller : MonoBehaviour
    
        private LifeBar bar;

        private void Start()
        
            Canvas canvas = FindObjectOfType<Canvas>();
            if (canvas == null)
            
                Debug.LogError("场景中没有Canvas组件");
                return;
            
            SpawnLifeBar(canvas);
        
        /// <summary>
        /// 生成血条
        /// </summary>
        /// <param name="canvas"></param>
        private void SpawnLifeBar(Canvas canvas)
        
            GameObject prefab = Resources.Load<GameObject>("LifeBar");
            bar = Instantiate(prefab, canvas.transform).AddComponent<LifeBar>();
            List<LifeBarDate> date = new List<LifeBarDate>();
            date.Add(new LifeBarDate(null, Color.green));
            date.Add(new LifeBarDate(null, Color.red));
            date.Add(new LifeBarDate(null, Color.yellow));
            bar.Init(transform, 350, date);
        
        /// <summary>
        /// 控制物体移动
        /// </summary>
        private void Update()
        
            if (Input.GetKey(KeyCode.A))
            
                Move(Vector3.left);
            
            if (Input.GetKey(KeyCode.D))
            
                Move(Vector3.right);
            
            if (Input.GetKey(KeyCode.W))
            
                Move(Vector3.up);
            
            if (Input.GetKey(KeyCode.S))
            
                Move(Vector3.down);
            

            if (Input.GetMouseButtonDown(0))
            
                int ran = Random.Range(10, 50);
                bar.ChangeLife(-ran);
            
            if (Input.GetMouseButtonDown(1))
            
                int ran = Random.Range(10, 50);
                bar.ChangeLife(ran);
            

        

        /// <summary>
        /// 物体移动
        /// </summary>
        /// <param name="dircetion"></param>
        private void Move(Vector3 dircetion)
        
            transform.Translate(dircetion * Time.deltaTime * 5);
        
    


2.创建LifeBar脚本

代码如下(示例):

using System.Collections.Generic;
using UnityEngine;

namespace HKZ

    public class LifeBar : MonoBehaviour
    
        private Transform _target;//要跟随的物体
        private Vector3 offset;//跟随物体的偏移量
        private List<LifeBarDate> Dates;
        private LifeBarItem nextBar;//下一个血条
        private LifeBarItem currentBar;//当前血条
        private float unitLifeScale;//血条大小
        private int currentIndex;//当前是哪个血条
        /// <summary>
        /// 初始化数据
        /// </summary>
        /// <param name="target"></param>
        /// <param name="lifeMax"></param>
        /// <param name="lifeBarDates"></param>
        public void Init(Transform target, int lifeMax, List<LifeBarDate> lifeBarDates)
        
            currentIndex = 0;
            _target = target;
            offset = GetOffset(target);
            Dates = lifeBarDates;
            nextBar = transform.Find("NextBar").gameObject.AddComponent<LifeBarItem>();
            currentBar = transform.Find("CurrentBar").gameObject.AddComponent<LifeBarItem>();
            nextBar.Init();
            currentBar.Init();

            RectTransform rect = GetComponent<RectTransform>();
            unitLifeScale = rect.rect.width * Dates.Count / lifeMax;//拿到血条大小

            SetBarDate(currentIndex, lifeBarDates);
        
        /// <summary>
        /// 得到目标物最上方位置
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        private Vector3 GetOffset(Transform target)
        
            Renderer renderer = target.GetComponent<Renderer>();
            if (renderer == null)
            
                return Vector3.zero;
            
            return Vector3.up * renderer.bounds.max.y;
        

        private void Update()
        
            if (_target == null)
            
                return;
            
            //跟随目标物
            transform.position = Camera.main.WorldToScreenPoint(_target.position + offset + new Vector3(0, 9, 0));
        
        /// <summary>
        /// 更新血条变化
        /// </summary>
        /// <param name="value"></param>
        public void ChangeLife(float value)
        
            float Width = currentBar.ChangeLife(value * unitLifeScale);
            if (Width < 0 && ChangeIndex(1))
            
                Exchange();
                currentBar.transform.SetAsLastSibling();
                nextBar.ResetToWidth();
                SetBarDate(currentIndex, Dates);
                ChangeLife(Width / unitLifeScale);
            
            else if (Width > 0 && ChangeIndex(-1))
            
                Exchange();
                currentBar.transform.SetAsLastSibling();
                currentBar.ResetToZero();
                SetBarDate(currentIndex, Dates);
                ChangeLife(Width / unitLifeScale);
            
        
        /// <summary>
        /// -1代表加血 1代表减血
        /// </summary>
        /// <param name="symbol"></param>
        private bool ChangeIndex(int symbol)
        
            int index = currentIndex + symbol;
            if (index >= 0 && index < Dates.Count)
            
                currentIndex = index;
                return true;
            
            return false;
        

        private void Exchange()
        
            var temp = nextBar;
            nextBar = currentBar;
            currentBar = temp;
        

        public void SetBarDate(int index, List<LifeBarDate> date)
        
            if (index < 0 || index >= date.Count)
            
                return;
            
            currentBar.SetDate(Dates[index]);

            if (index + 1 >= date.Count)
            
                nextBar.SetDate(new LifeBarDate(null, Color.white));
            
            else
            
                nextBar.SetDate(date[index + 1]);
            
        
    
    /// <summary>
    /// 血条数据
    /// </summary>
    public struct LifeBarDate
    
        public Sprite BarSprite;
        public Color BarMainColor;

        public LifeBarDate(Sprite barSprite, Color barMainColor)
        
            BarSprite = barSprite;
            BarMainColor = barMainColor;
        
    


3.创建LifeBarItem脚本

代码如下(示例):

using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;

namespace HKZ

    public class LifeBarItem : MonoBehaviour
    
        private RectTransform rect;
        public RectTransform Rect
        
            get
            
                if (rect == null)
                
                    rect = GetComponent<RectTransform>();
                
                return rect;
            
        
        private Image image;
        public Image Image
        
            get
            
                if (image == null)
                
                    image = GetComponent<Image>();
                
                return image;
            
        

        private float defaultWidth;
        private LifeBarItem child;
        /// <summary>
        /// 初始化数据
        /// </summary>
        public void Init()
        
            if (transform.Find("AdditionBar") != null)
            
                child = transform.Find("AdditionBar").gameObject.AddComponent<LifeBarItem>();
            
            defaultWidth = Rect.rect.width;
        
        /// <summary>
        /// 设置数据
        /// </summary>
        /// <param name="date"></param>
        public void SetDate(LifeBarDate date)
        
            Image.color = date.BarMainColor;
            if (date.BarSprite != null)
            
                Image.sprite = date.BarSprite;
            

            if (child != null)
            
                child.SetDate(date);
            
        
        /// <summary>
        /// 更变血条
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public float ChangeLife(float value)
        
            if (child != null)
            
                child.DOKill();
                child.Image.color = Image.color;
                child.Rect.sizeDelta = Rect.sizeDelta;
                child.Image.DOFade(0, 0.5f).OnComplete(() => child.ChangeLife(value));
            

            Rect.sizeDelta += Vector2.right * value;

            return GetOutRange();
        
        /// <summary>
        /// 得到当前血条
        /// </summary>
        /// <returns></returns>
        private float GetOutRange()
        
            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;
        
        /// <summary>
        /// 扣血显示下一条时恢复默认状态
        /// </summary>
        public void ResetToZero()
        
            Rect.sizeDelta = Vector2.zero;
        
        /// <summary>
        /// 加血显示下一条时恢复默认状态
        /// </summary>
        public void ResetToWidth()
        
            Rect.sizeDelta = Vector2.right * defaultWidth;
        
    


效果出来了吧!


总结

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

Unity3D 血条的渐变效果

Unity3D 血条的渐变效果

unity3d中怎样制作血条跟随角色运动

解决Unity3D中多层级结构子物体旋转受父物体尺寸影响的问题

解决Unity3D中多层级结构子物体旋转受父物体尺寸影响的问题

解决Unity3D中多层级结构子物体旋转受父物体尺寸影响的问题