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
}
Damageable.cs
最新推荐文章于 2021-08-12 23:22:03 发布