using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Reflection; using System.Threading.Tasks; using UnityEditor; using UnityEngine; using UnityEngine.UI; using UnityEngine.UIElements; using Debug = UnityEngine.Debug; using Image = UnityEngine.UI.Image; using DG.Tweening; using UnityEngine.SocialPlatforms; public enum Camp {/// /// 玩家 /// Player, /// /// 怪物 /// Enemy, /// /// 中立 /// Neutral } /// /// 角色基类,玩家处理事件 /// [ExecuteInEditMode] public class Role : Fun { [Header("Id")] public string id; [Header("阵营")] public Camp camp ; [Header("血量")] public float hp = 100f;//血量 private float maxHp; [Header(("死亡动画编号"))] public int dieIndex=-1; [Header("hp填充直接扣")] public Image Hpfiil; [Header("hp填充慢慢扣")] public Image HpfiilYello; [Header("扣血填充")] public GameObject HpTextPrefab; [Header("自己的画布")]public Canvas _Canvas; [Header("自己的图片")] public SpriteRenderer spriteRenderers; // 存储所有的SpriteRenderer组件 [Header("被打的方向")] public int HurtDirectin; public string Quality;//品质 public string Elements;//属性 public string Info;//详情 public string SkillId;//技能 public string AttackType;//攻击类型 public string AttackActionType;//攻击作用类型 public float AttackRange { get; set; }//攻击范围 public float AttackCD;//攻击CD public float CritRate;//暴击率 public float CriticalHitRateBonus;//暴击加成 public float Hp { get => hp; set { float temp = hp; hp = value; // 更新血条显示 if (Hpfiil != null) { Hpfiil.fillAmount = hp / maxHp; // 使用 DOTween 动画平滑过渡血条填充 DOTween.To(() => HpfiilYello.fillAmount, x => HpfiilYello.fillAmount = x, hp / maxHp, 0.8f) // 0.5f 为过渡时间 .SetEase(Ease.InOutQuad); // 使用缓动效果,使血条变化更加平滑 } // 更新血量文本效果 if (HpTextPrefab != null && hp < maxHp) { hit(); Navigation.StopPathDoTween(0.2f); // 停止任何进行中的 DoTween 动画,0.2s为示例值 GameObject go = GameObject.Instantiate(HpTextPrefab, _Canvas.transform); go.GetComponent().direction = HurtDirectin; go.GetComponent().CreateText(); go.GetComponent().text = (temp - hp).ToString("F0"); // 显示伤害值 FlashRedEffect(); // 血量减少时的红色闪烁效果 } // 判断角色是否死亡 if (hp <= 0) { die(); // 执行死亡处理 } } } [Header("掉落")] public float gold = 10f; public float Gold { [DebuggerStepThrough] get => gold; [DebuggerStepThrough] set => gold = value; } [Header("攻击力")] private float attack = 10f; [Header("攻击力上限")] public float MaxAttack = 10f; [Header("攻击力下限")] public float MinAttack = 10f; public float Attack { get => attack; set => attack = value; } [Header("等级")] private int level = 1; public int Level { [DebuggerStepThrough] get => level; [DebuggerStepThrough] set => level = value; } [Header("物理护甲")] public int physicalArmor = 10;//物理护甲 [Header("魔法护甲")] public int magicArmor = 5;//魔法护甲 [Header("导航组件")] public SimplePathfindingDoTween Navigation; [System.Serializable ] public class AnimationList//动画list { //[Header("动画是否循环")] public bool isloop = false; [Header("动画图片")] public List value; // 字典的值 [Header("角色动画帧数间隔(毫秒)")] public int CharacterAnimationFrameInterval = 50; } [Header("角色动画")] public List AnimationTree = new List(); [Header("角色动画播放")] public int animationHighlight = 0; [Header("角色精灵位置")] public SpriteRenderer spriteRenderer; [Header("角色Image位置")] public Image image; public delegate void AnimationItem(int AnimationItem); public event AnimationItem OnAnimationStart; public event AnimationItem OnAnimationIng; public event AnimationItem OnAnimationEnd; [Header("动画是否正常播放")] public bool isAnimationPlay = false;//动画是否正常播放 [Header("碰撞体")]public CircleCollider2D mycollider; [Header("攻击脚本")] public Attack attackClass; [Header("当前播放图片序列")] public int CurrentIndex; public int hitIndex = 2;//受击动画索引 public int normalIndex = 0;//移动动画索引 public bool isHit=false;// public List buffList = new List(); /// /// 储存buff /// public List> storageBuff = new List>(); /// /// 使用buff /// public List> PlayerBuff=new List>(); public virtual async void Start() { maxHp = hp; SetSelfInfo(); if (Application.isPlaying) { if (attackClass) { attackClass.role = this; } UpdateBuff(); } tag = Enum.GetName(typeof(Camp), camp); updateAnimation(); //ApplyBuffs(); } /// /// 添加Buff /// /// public void AddBuff(List> buffs, Action buffAction) { buffs.Add(buffAction); } /// /// 执行所有当前 Buff /// public void ApplyBuffs() { foreach (var buff in PlayerBuff) { buff.Invoke(this); // 将自己作为目标传递 } // 清空 Buff 列表,假设 Buff 是一次性的 PlayerBuff.Clear(); } /// /// 角色动画更新 /// public async void updateAnimation() { while (true) { if (AnimationTree.Count == 0) { isAnimationPlay = false; return; } isAnimationPlay = true; if (animationHighlight >= AnimationTree.Count) { animationHighlight = AnimationTree.Count - 1; } else if (animationHighlight < 0) { animationHighlight = 0; } List LightSprite = AnimationTree[animationHighlight].value; if (LightSprite == null) { isAnimationPlay = false; return; }; OnAnimationStart?.Invoke(animationHighlight); var lsanimationHighlight = animationHighlight; foreach (Sprite sprite in LightSprite) { if (lsanimationHighlight == animationHighlight) { if (image != null) { image.sprite = sprite; } else if (spriteRenderer != null) { spriteRenderer.sprite = sprite; } if (animationHighlight >= 0 && animationHighlight < AnimationTree.Count) { OnAnimationIng?.Invoke(animationHighlight); await Task.Delay(AnimationTree[animationHighlight].CharacterAnimationFrameInterval); } } else { break; } } OnAnimationEnd?.Invoke(lsanimationHighlight); if (lsanimationHighlight == dieIndex) { SpawnPool.intance.ReturnEnemyToPool(this.gameObject); // 回收当前敌人到池中 ResetAllStatus(); } if (lsanimationHighlight == hitIndex) { animationHighlight = normalIndex; } } } /// /// 角色死亡 /// public virtual void die() { if (Application.isPlaying) { animationHighlight = dieIndex; Navigation.PauseAnimation(); Debug.Log("die"); } } /// /// 角色受到攻击 /// public virtual void hit() { if (Application.isPlaying) { animationHighlight = hitIndex; } } /// /// 角色减速 /// public void SlowDown(float num) { Navigation.speedFactor *= num; } /// /// 单位更新buff /// async void UpdateBuff()//单位buff更新 { while (true) { List deleteArr = new List(); foreach (BUff buffItem in buffList) { if (buffItem.executionInterval <= 0) { buffItem.executionInterval = buffItem.executionInterval_max; buffItem.Funaction.Invoke(buffItem.value); } buffItem.executionInterval -= 0.1f; buffItem.timeLeft -= 0.1f; if (buffItem.timeLeft <= 0) { deleteArr.Add(buffItem); } } foreach (BUff item in deleteArr) { buffList.Remove(item); } await Task.Delay(100);//buff检测最小时间0.1秒执行一次 } } /// /// 重置角色所有状态 /// public void ResetAllStatus() { // 重置血量 Hp = 100f; // 重置攻击力 Attack = 10f; // 重置护甲 physicalArmor = 10; magicArmor = 5; // 重置等级 Level = 1; // 重置金币 Gold = 10f; // 清空 Buff 列表 buffList.Clear(); // 如果有导航组件,停止当前的导航行为 if (Navigation != null) { //Navigation.Stop(); // 假设你有 Stop 方法来停止导航 } // 重置角色动画 animationHighlight = 0; isAnimationPlay = false; // 重置碰撞体(根据需求是否需要调整) if (mycollider != null) { mycollider.enabled = true; // 启用碰撞体 } // 如果有其他需要重置的状态,可以在这里添加 } private void FlashRedEffect() { // 遍历所有的SpriteRenderer组件,让它们变红 if (spriteRenderer != null) { spriteRenderer.DOColor(UnityEngine.Color.red, 0.2f) .OnComplete(() => { // 恢复原始颜色 spriteRenderer.DOColor(UnityEngine.Color.white, 0.2f); }); } } public void StopDoTween(float stopTime) { // 暂停当前的动画 transform.DOPause(); // 插入一个自定义的延迟(僵直时间) DOTween.To(() => 0f, x => { }, 0f, stopTime).OnKill(() => { // 在延迟结束后恢复动画 transform.DOPlay(); }); } // 升级逻辑 public virtual void Upgrade() { Debug.Log("父类的升级逻辑,空的,请在子类重写"); } public void SetSelfInfo() { if (camp==Camp.Player) { Debug.Log("攻击力赋值==============================" + MengyaoInfo.Instance.m_Mengyao.Count); foreach (Character character in MengyaoInfo.Instance.m_Mengyao) { if (id ==character.Id) { MinAttack = int.Parse(character.MinAttack); MaxAttack = int.Parse(character.MaxAttack); AttackCD = float.Parse(character.AttackCD); CritRate = float.Parse(character.CritRate); Quality=character.Quality;//品质 Elements=character.Elements;//属性 Info=character.Info;//详情 SkillId=character.SkillId;//技能 AttackType=character.AttackType;//攻击类型 AttackActionType=character.AttackActionType;//攻击作用类型 CriticalHitRateBonus = float.Parse(character.CriticalHitRateBonus); Debug.Log("攻击力赋值++++++++++++++++++++++++++++++"); } } } } public float DamageCreate()//伤害生成 { // 生成普通伤害 float num = UnityEngine.Random.Range(MinAttack, MaxAttack); // 判断是否暴击 float critChance = UnityEngine.Random.Range(0f, 1f); // 生成一个0到1之间的随机数 if (critChance < CritRate) // 如果暴击发生 { // 计算暴击伤害(普通伤害乘以暴击加成) num *= (1 + CriticalHitRateBonus); Debug.Log("暴击发生!伤害增加:" + num); } return num; } }