Damageable.cs

using UnityEngine;
using System.Linq;
using System.Collections;
using System.Collections.Generic;

public class Damageable : MonoBehaviour
{
    public const string BloodbarTexture = "Texture/attach/color/blank";
    public enum ESpecialState { Normal, Invincibility, Bleeding }//特殊状态枚举: 正常,无敌,流血
    public float Health = 100;//自身生命值上限
    public float Damage = 0;//攻击时伤害值
    public float DamageSec = 0;//持续攻击(例如流血)时间
    public ESpecialState SpecialState = ESpecialState.Normal;//默认为普通状态
    public bool CanSelfdestruct = true;//默认可以自毁,在特定情况下自毁由动画实体处理,所以此选项根据需要自由设定
    public bool IsShowBloodbar = false;//默认不显示血条
    public Color BloodbarColor = Color.red;//血条默认红色
    public float CurrentHealth { get; private set; } //获取当前生命值
    public float HealthPercent { get { return CurrentHealth / Health; } }//获取生命值百分比
    public bool IsAlive { get; private set; }

    static Texture m_Bloodbar;
    static UIRoot m_Root;
    static Camera m_Camera;
    float m_getHurt;//受到伤害值,用于计算持续伤害
    float m_getHurtSec;//受到伤害持续时间
    GameObject m_bloodbar;

    #region 静态函数
    //判断是否有攻击组件
    public static bool IsHasComponent(GameObject target)
    {
        var result = false;
        try
        {
            if (target.GetComponent<Damageable>() != default(Damageable)) result = true;
        }
        catch
        {
            result = false;
        }
        return result;
    }

    //判断是否可攻击
    public static bool IsCanHurt(GameObject target)
    {
        var result = false;
        try
        {
            if (target.GetComponent<Damageable>().SpecialState != ESpecialState.Invincibility) result = true;
        }
        catch
        {
            result = false;
        }
        return result;
    }

    //找到所有可攻击目标
    public static List<Damageable> GetAllTargetList()
    {
        return ((Damageable[])FindObjectsOfType(typeof(Damageable))).ToList();
    }

    //获取指定标签匹配的攻击列表
    public static List<Damageable> GetTargetList(string targetTag)
    {
        return GetAllTargetList().FindAll(t => t.tag.Equals(targetTag));
    }

    //获取所有标签匹配的攻击列表
    public static List<Damageable> GetTargetList(string[] targetTags)
    {
        var getList = GetAllTargetList();
        var targetList = new List<Damageable>();
        for (var i = 0; i < targetTags.Length; i++)
        {
            targetList.AddRange(getList.FindAll(t => t.tag.Equals(targetTags[i])));
        }
        return targetList;
    }

    //判断目标是否在攻击列表内,必须是同类型才可以判断
    public static bool HasTargetListIncludeThis(Damageable currentTarget, List<Damageable> targetList)
    {
        return targetList.Contains(targetList.Find(t => t.GetInstanceID().Equals(currentTarget.GetInstanceID())));
    }

    //根据当前位置和搜索范围过滤攻击列表
    public static List<Damageable> GetAreaDamageFilter(List<Damageable> targetList, Vector3 position, float searchRange)
    {
        var damageList = new List<Damageable>();
        for (var i = 0; i < targetList.Count; i++)
        {
            var myPos = m_Camera.WorldToScreenPoint(position);
            var targetPos = m_Camera.WorldToScreenPoint(targetList[i].transform.position);
            var distance = (targetPos - myPos).magnitude;
            if (distance < searchRange)
            {
                damageList.Add(targetList[i]);
            }
        }
        return damageList;
    }

    //伤害结算
    public static void HurtAccount(List<Damageable> damageList, float damage)
    {
        for (var i = 0; i < damageList.Count; i++)
        {
            damageList[i].Hurt(damage);
        }
    }

    #endregion

    #region 系统调用
    void Awake()
    {
        m_Bloodbar = Resources.Load<Texture>(BloodbarTexture);
    }

    void Start()
    {
        //设置相机
        m_Root = FindObjectOfType<UIRoot>();
        m_Camera = m_Root.transform.FindChild("Camera").GetComponent<Camera>();
        //初始化参数
        IsAlive = true;//默认存活
        Health = Mathf.Abs(Health);//默认以绝对值为生命值点数以防止输入为负数情况
        CurrentHealth = Health;//初始化当前生命值
        m_getHurt = 0;
        m_getHurtSec = 0;
        //删除现有血条
        try
        {
            m_bloodbar = transform.FindChild("bloodbar").gameObject;
            m_bloodbar.transform.SetParent(null);
            DestroyObject(m_bloodbar);
        }
        catch
        {
            m_bloodbar = null;
        }
        //判断是否显示血条
        if (IsShowBloodbar)
        {
            var sprite = GetComponent<UISprite>();
            m_bloodbar = new GameObject("bloodbar");
            m_bloodbar.transform.SetParent(transform);
            m_bloodbar.transform.localScale = Vector3.one;//设置尺寸
            m_bloodbar.layer = transform.parent.gameObject.layer;
            m_bloodbar.AddComponent<UITexture>();
            m_bloodbar.GetComponent<UITexture>().mainTexture = m_Bloodbar;
            m_bloodbar.GetComponent<UITexture>().width = sprite.width;
            m_bloodbar.GetComponent<UITexture>().height = 15;
            m_bloodbar.GetComponent<UITexture>().type = UIBasicSprite.Type.Filled;
            m_bloodbar.GetComponent<UITexture>().fillDirection = UIBasicSprite.FillDirection.Horizontal;
            m_bloodbar.GetComponent<UITexture>().color = BloodbarColor;
            m_bloodbar.transform.localPosition = new Vector2(0, (float)(sprite.height + m_bloodbar.GetComponent<UITexture>().height) / 2);
            m_bloodbar.SetActive(true);
            StartCoroutine(delayHideBloodbar());//开启协程
        }
        else
        {
            if (m_bloodbar != default(GameObject)) m_bloodbar.SetActive(false);
            StopCoroutine(delayHideBloodbar());//关闭协程
        }
    }

    void Update()
    {
        if (CurrentHealth > 0)
        {//判定为存活
            if (m_getHurtSec > 0)
            {//有未结算的持续伤害
                var sec = Time.deltaTime;
                m_getHurtSec -= sec;//结算持续伤害时间
                var hurt = Mathf.RoundToInt(m_getHurt / m_getHurtSec / sec);
                m_getHurt -= hurt;//结算剩余伤害
                CurrentHealth -= hurt;//结算当前生命值
            }
        }
        else
        {//判定为死亡
            Killed();//死亡结算
        }
    }

    #endregion

    #region 伤害结算
    //摧毁处理
    void OnDestroy()
    {
        IsAlive = false;
        gameObject.tag = "Untagged";
    }

    //一次性伤害
    public void Hurt(float damage)
    {
        if (SpecialState == ESpecialState.Invincibility) return;//无敌时退出
        CurrentHealth -= damage;//直接扣除伤害值
        if (IsShowBloodbar) showBloodbar();
    }

    //持续性伤害
    public void Hurt(float damage, float damageSec)
    {
        if (SpecialState == ESpecialState.Invincibility) return;//无敌时退出
        m_getHurt += damage;//叠加伤害
        m_getHurtSec += damageSec;//叠加时间
        if (IsShowBloodbar) showBloodbar();
    }

    //击杀结算
    public void Killed()
    {
        IsAlive = false;
        CurrentHealth = 0;
        m_getHurt = 0;
        m_getHurtSec = 0;
        SpecialState = ESpecialState.Normal;
        if (CanSelfdestruct) DestroyObject(gameObject);
    }

    #endregion

    #region 血条处理
    //显示血条
    void showBloodbar()
    {
        if (!IsAlive || m_bloodbar == default(GameObject)) return;
        m_bloodbar.GetComponent<UITexture>().fillAmount = HealthPercent;//实时读取血条
        m_bloodbar.SetActive(true);
        delayHideBloodbar();
    }

    //等待2秒后隐藏血条
    IEnumerator delayHideBloodbar()
    {
        while (IsAlive)
        {
            yield return new WaitForSeconds(2);
            try
            {
                m_bloodbar.SetActive(false);
            }
            catch
            {
                // ignored
            }
        }
    }

    #endregion

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值