Unity UI血条制作

为了避免策划有屏幕上显示多个boss的血条的需求,设计血条需要考虑多个的情况。
例如:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
利用列表的control child size和item里面的锚点定好来实现。
在这里插入图片描述
在分享一段boss多段血条加上血条缓冲的代码:

  [LuaCallCSharp]
    public class BossBlood:MonoBehaviour
    {
        private static int s_lastID;
        private static BossBlood s_target;
        public static void OnObj(int nID)
        {
            if(s_lastID!=nID)
            {
               //获得s_target
            }
        }
        public static void ResetBlood(int nID)
        {
            OnObj(nID);
            s_target.ResetBlood(); 
        }
        public static void InitBlood(int nID,Int64 uid)
        {
            OnObj(nID);
            s_target.InitBlood(uid);
        }
        public static void Play(int nID)
        {
            OnObj(nID);
            s_target.Play();
        }
        struct BloodState
        {
            public int curHp;
            public int maxHp;
            public int topColorIndex;
            public int bloodLayer;
        }
        public Image img_top;
        public Image img_buffer;
        public Image img_bottom;
        public TextMeshProUGUI text_bloodNum;
        private IMonster monster;
        private cfg_Monster cfg;
        private bool isPlay = false;
        private BloodState bloodState; //播完之后终止的状态
        public void ResetBlood()
        {
            isPlay = false;
            img_top.color = new Color(img_top.color.r,img_top.color.g,img_top.color.b,0);
            img_bottom.color = new Color(img_bottom.color.r, img_bottom.color.g, img_bottom.color.b, 0);
            this.monster = null;
        }
        public void InitBlood(Int64 uid)
        {
            this.monster = rkt.Common.GameHelp.GetEntityByUID(uid) as IMonster;
            int curHp = monster.GetNumProp((int)EMCREATURE_PROP.CREATURE_PROP_CUR_HP);
            int maxHp = monster.GetNumProp((int)EMCREATURE_PROP.CREATURE_PROP_MAX_HP);
            if(curHp<=0)
            {
                Debug.LogError($"init , curhp == 0");
                ResetBlood();
                return;
            }
            int decreaseHp = maxHp - curHp; // 当前减少的血量
            cfg = this.monster.GetMonsterCfg();
            int totalBloodNum = GetCfgBloodNum(cfg);
            float stepBloodValue = 1 / (float)totalBloodNum * maxHp;
            int decreaseBloodNum = Mathf.FloorToInt(decreaseHp / stepBloodValue);
            int remainBloodNum = totalBloodNum - decreaseBloodNum;
            text_bloodNum.SetText("X"+remainBloodNum);
            int topColorIndex = GetTopColorIndex(decreaseBloodNum);
            SetHpColor(img_top,topColorIndex);
            float topHpRate = 1- (decreaseHp - decreaseBloodNum * stepBloodValue) / (float)stepBloodValue;
            SetHpRate(img_top, topHpRate);
            SetHpRate(img_buffer, topHpRate);
            int bottomColorIndex = GetBottomColorIndex(topColorIndex, remainBloodNum);
            SetHpColor(img_bottom, bottomColorIndex);
            SetHpRate(img_bottom, 1);
            SaveBloodState(maxHp,curHp, remainBloodNum, topColorIndex);
        }
        private int GetCfgBloodNum(cfg_Monster cfg)
        {
            if (cfg.nBloodNum > 0)
                return cfg.nBloodNum;
            return 1;
        }
        private void SaveBloodState(int maxHp,int curHp,int bloodLayer,int topColorIndex)
        {
            bloodState.maxHp = maxHp;
            bloodState.curHp = curHp;
            bloodState.bloodLayer = bloodLayer;
            bloodState.topColorIndex = topColorIndex;
        }
        public void Play()
        {
            if (IsNeedInitBlood()) //是否跨段
            {
                //加血
                InitBlood(monster.GetUID());
                return;
            }
            isPlay = true;
        }
        private bool IsNeedInitBlood()
        {
            int curHp = monster.GetNumProp((int)EMCREATURE_PROP.CREATURE_PROP_CUR_HP);
            int maxHp = monster.GetNumProp((int)EMCREATURE_PROP.CREATURE_PROP_MAX_HP);
            int decreaseHp = maxHp - curHp; // 当前减少的血量
            int totalBloodNum = GetCfgBloodNum(cfg);
            float stepBloodValue = 1 / (float)totalBloodNum * maxHp;
            int decreaseBloodNum = Mathf.FloorToInt(decreaseHp / stepBloodValue);
            int remainBloodNum = totalBloodNum - decreaseBloodNum;
            if (remainBloodNum > bloodState.bloodLayer)
            {
                return true;
            }
            if(!isPlay)
            {
                if(curHp > this.bloodState.curHp)
                {
                    return true;
                }
                if(maxHp!=this.bloodState.maxHp)
                {
                    return true;
                }
            }
            return false;
        }
        private bool SetBloodBuffer()
        {
            float needRate = this.img_top.fillAmount;
            float nowRate = this.img_buffer.fillAmount;
            if (nowRate <= needRate)
            {
                this.img_buffer.fillAmount = needRate;
                return true;
            }
            if(Mathf.Abs(needRate-nowRate)<0.01f)
            {
                this.img_buffer.fillAmount = needRate;
                return true;
            }
            nowRate = Mathf.Lerp(nowRate, needRate, Time.deltaTime*5);
            this.img_buffer.fillAmount = nowRate;
            return false;
        }
        public void Update()
        {
            if(isPlay)
            {
                int curHp = monster.GetNumProp((int)EMCREATURE_PROP.CREATURE_PROP_CUR_HP);
                int maxHp = monster.GetNumProp((int)EMCREATURE_PROP.CREATURE_PROP_MAX_HP);
                if (curHp <= 0)
                {
                    Debug.LogError($"update , curhp == 0");
                    ResetBlood();
                    return;
                }
                int decreaseHp = maxHp - curHp; // 当前减少的血量
                int totalBloodNum = GetCfgBloodNum(cfg);
                float stepBloodValue = 1 / (float)totalBloodNum * maxHp;
                int decreaseBloodNum = Mathf.FloorToInt(decreaseHp / stepBloodValue);
                int remainBloodNum = totalBloodNum - decreaseBloodNum;
                if(remainBloodNum<bloodState.bloodLayer)
                {
                    SetHpRate(img_top, 0);
                    if(SetBloodBuffer())
                    {
                        // 读完一段
                        SaveBloodState(maxHp,curHp, remainBloodNum, GetTopColorIndex(decreaseBloodNum));
                        int topColorIndex = GetTopColorIndex(decreaseBloodNum);
                        SetHpColor(img_top, topColorIndex);
                        SetHpRate(img_top,1);
                        SetHpColor(img_bottom, GetBottomColorIndex(topColorIndex, remainBloodNum));
                        SetHpRate(img_bottom, 1);
                        text_bloodNum.SetText("X" + remainBloodNum);
                    }
                    return;
                }
                else if(remainBloodNum>bloodState.bloodLayer)
                {
                    Debug.LogError($"{remainBloodNum}大于当前层数,不可能");
                }
                float topHpRate =1- (decreaseHp - decreaseBloodNum * stepBloodValue) / (float)stepBloodValue;
                SetHpRate(img_top,topHpRate);
                if(SetBloodBuffer())
                {
                    SaveBloodState(maxHp,curHp,remainBloodNum,GetTopColorIndex(decreaseBloodNum));
                    isPlay = false;
                }
            }
        }
        private void SetHpRate(Image img,float rate) {
            img.fillAmount = rate;
        }
        private void SetHpColor(Image img,int colorIndex)
        {
            if(colorIndex!=-1)
            {
                SpriteSwitcher target = img.GetComponent<SpriteSwitcher>();
                if (target)
                    target.Switch(colorIndex);
                img.color = new Color(img.color.r,img.color.g,img.color.b,1);
            }
            else
            {
                img.color = new Color(img.color.r, img.color.g, img.color.b, 0);
            }
        }
        private int GetBottomColorIndex(int topColorIndex,int remainBloodNum)
        {
            int result = topColorIndex - 1<0?4:topColorIndex-1;
            if(remainBloodNum==1)
            {
                result = -1;
            }
            return result;
        }
        private int GetTopColorIndex(int decreaseBloodNum)
        {
            int totalBloodNum = GetCfgBloodNum(cfg);
            int result = totalBloodNum - 1;
            if (result > 5)
            {
                int resultNum = totalBloodNum % 5;
                result = resultNum == 0 ? 4 : resultNum - 1;
            }// 起始位置
            while (decreaseBloodNum>0)
            {
                result--;
                if (result < 0) result = 4;
                --decreaseBloodNum;
            }
            return result;
        }

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JustEasyCode

谢谢您

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值