主要代码逻辑是创建一个action队列,当动画播放结束时就移除队头,执行后面的事件
-
- public class Enemy : MonoBehaviour
- {
-
-
- public event Action E_AnimatorFin;//当动画播放完毕时
-
- public Action DefaultAction;//默认事件
-
- public Dictionary
string> EventAnimator= new();//Event对应的动画 - public List
Eventlist=new();//要做的event列表 -
- private Animator ani;
-
-
- public virtual void Start()
- {
-
- ani = GetComponent
(); - E_AnimatorFin += OnAnimatorFinish;
-
- StartCoroutine(SpawningAnimator());
- IEnumerator SpawningAnimator()
- {
- yield return new WaitForSeconds(0.02f);
- PlayAnimator(ani, EventAnimator[ Eventlist[0]],
- () =>
- {
- Debug.Log("动画播放前执行代码"+ EventAnimator[ Eventlist[0]]);
- },
- () =>
- {
- E_AnimatorFin?.Invoke();
- Debug.Log("动画播放完执行代码");
- });
- }
-
- }
-
-
-
- public virtual void OnAnimatorFinish()
- {
- StartCoroutine(spawnanimator());
- IEnumerator spawnanimator()
- {
-
- yield return new WaitForSeconds(0.02f);
- if (Eventlist.Count == 0)
- {
- Eventlist.Add(DefaultAction);
- Debug.LogWarning(name+$"并没有新的事件,目前在执行默认的事件");
- }
-
-
-
- try
- {
- PlayAnimator(ani, EventAnimator[ Eventlist[0]],
- () =>
- {
- Debug.LogError($"执行前{EventAnimator[ Eventlist[0]]}");
- Eventlist[0]();
- },
- () =>
- {
- Debug.LogError("执行完");
- E_AnimatorFin?.Invoke();
- });
- }
- catch (KeyNotFoundException e)
- {
- Debug.LogError(Eventlist[0].Method.Name+"没有匹配动画!");
- }
- Eventlist.RemoveAt(0);
- }
-
- }
-
-
-
- #region Animator
- public void PlayAnimator(Animator animator, string clipName, Action startAct = null, Action endAct = null)
- {
- StartCoroutine(PlayAnimationItor(animator, clipName, startAct, endAct));
- }
-
- ///
- /// Animation动画播放迭代器
- ///
- /// Animation组件
- /// clip片段名
- /// 委托函数
- /// 委托函数
- ///
- private IEnumerator PlayAnimationItor(Animator animator, string clipName, Action startAct=null, Action endAct=null)
- {
- startAct?.Invoke();
- animator.Play(clipName);
- // 获取目标动画的名称
- string targetClipName =clipName;
- yield return StartCoroutine(WaitForEndOfAnimr(targetClipName));
- IEnumerator WaitForEndOfAnimr(string targetName)
- {
- yield return new WaitForSeconds(0.1f);//为过渡动画预留时间
- AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(0);
- Debug.Log("Targetname>>"+targetName);
- while (animator.GetCurrentAnimatorStateInfo(0).IsName(targetName))
- {
- // 获取当前动画片段信息
- clipInfo = animator.GetCurrentAnimatorClipInfo(0);
- if (clipInfo.Length > 0)
- {
- // 获取当前播放的动画片段的名称
- string currentClipName = clipInfo[0].clip.name;
- Debug.Log("当前播放的动画片段名称: " + currentClipName);
- }
-
- yield return new WaitForSeconds(0.01f);
- }
- }
- // Debug.LogError($"{animator.GetCurrentAnimatorClipInfo(0)[0].clip.name}+{targetClipName}");
- endAct?.Invoke();
- }
-
-
-
- #endregion
-
- #region AI逻辑
-
- ///
- /// 设置没有事件列表时自动执行的事件
- ///
- ///
- public void SetDefaultEvent(Action t)
- {
- DefaultAction = t;
- }
- ///
- /// 为怪物添加一个事件到列表
- ///
- ///
- public void AddEvent(Action action)
- {
- Eventlist.Add(action);
- }
-
- ///
- /// 重置怪物事件列表为一个新的列表
- ///
- ///
- public void SetEvent(Action[] actions)
- {
- foreach (var VARIABLE in Eventlist)
- {
- Eventlist.Remove(VARIABLE);
- }
-
- foreach (var VARIABLE in actions)
- {
- Eventlist.Add(VARIABLE);
- }
- }
-
- ///
- /// 强制加入一个事件到下一个行动
- ///
- /// 增加的事件
- public void NextEvent(Action addAction)
- {
- Debug.Log("length="+Eventlist.Count);
- if (Eventlist.Count>0)
- {
- Eventlist.Insert(1,addAction);
- }
- else
- {
- Eventlist.Add(addAction);
- }
-
- }
-
- ///
- /// 强制指定下一个事件且立刻执行
- ///
- ///
- public void DoNextEvent(Action addAction)
- {
- StopAllCoroutines();
- NextEvent(addAction);
- if (Eventlist.Count>1)
- {
- Eventlist.RemoveAt(0);
- }
-
-
- PlayAnimator(ani, EventAnimator[ Eventlist[0]],
- () =>
- {
- Eventlist[0]();
- Debug.Log("动画播放前执行代码"+ EventAnimator[ Eventlist[0]]);
- },
- () =>
- {
- E_AnimatorFin?.Invoke();
- Debug.Log("动画播放完执行代码");
- });
-
-
- }
-
- #endregion
-
使用示例
- public class Cow : Enemy
- {
- private GameObject normalATK;
- public void Awake()
- {
- normalATK = transform.Find("NormalATK").gameObject;
- normalATK.SetActive(false);
-
- EventAnimator.Add(AI_DoRandomRelex,"Start");//为事件指定对应动画
- EventAnimator.Add(Animator_Idle,"idle");
- EventAnimator.Add(Animator_Rest,"rest");
- EventAnimator.Add(AI_FindPlayer,"walk");
- EventAnimator.Add(AI_Attack,"attack");
- SetDefaultEvent(AI_DoRandomRelex);//设置默认动画
- AddEvent(DefaultAction);//添加默认动画
-
- E_HPChanged += () => {Debug.LogError("收到伤害"); };
- E_HPChanged += ToHostile;//收到伤害时敌对
- }
-
- ///
- /// 收到伤害的时候调用,改为攻击模式
- ///
- void ToHostile()
- {
- DoNextEvent(AI_FindPlayer);
- SetDefaultEvent(AI_FindPlayer);
- FriendlyTag = FriendlyLevel.Hostile;
-
- }
- public void AI_DoRandomRelex()//中立状态时随机做待机动画
- {
- int rd = Random.Range(0, 100);
- if (rd<51)
- {
- Debug.Log("next>>idle");
- NextEvent(Animator_Idle);
- }
- else
- {
- Debug.Log("next>>rest");
- NextEvent(Animator_Rest);
- }
- }
- private void Animator_Idle()//待机动画只有动画效果,没有要执行的内容
- {
- Debug.Log("IDLE");
- }
-
- private void Animator_Rest()
- {
- Debug.Log("REST");
- }
- private void Debug3()
- {
-
- }
-
- bool finder;//只有在事件进行的时候才追踪.当事件结束后退出追踪循环
- public override void AI_FindPlayer()//在敌对状态默认追踪玩家
- {
-
- finder = true;
- StartCoroutine(basefind());
-
- E_AnimatorFin += setfinder;
- IEnumerator basefind()
- {
- while (finder)
- {
- base.AI_FindPlayer();
- yield return new WaitForSeconds(0.1f);
- }
-
- E_AnimatorFin -= setfinder;
- }
- void setfinder()
- {
- finder = false;
- }
-
- StartCoroutine(atrange());
- E_AnimatorFin += () => { StopCoroutine(atrange()); };
- IEnumerator atrange()
- {
- do
- {
- if (IsPlayerInAttackRange)//如果玩家在攻击范围内就进行攻击事件
- {
- DoNextEvent(AI_Attack);
- }
- yield return new WaitForSeconds(0.02f);
- } while (true);
- }
-
- }
-
- public void AI_Attack()//攻击事件
- {
- base.AI_FindPlayer();
- Debug.LogError("AIATK");
- StartCoroutine(WaitATK());
- E_AnimatorFin += () => {des(); };
- IEnumerator WaitATK()
- {
- yield return new WaitForSeconds(0.2f * EventSpeed);
- normalATK.SetActive(true);
- }
- void des()
- {
- normalATK.SetActive(false);
- E_AnimatorFin -= des;
- }
- }
-
- public override void Update()
- {
- base.Update();
-
- //如果玩家在索敌范围外就变回中立
- if (!IsPlayerInFindingRange&& (FriendlyTag == FriendlyLevel.Hostile))
- {
- FriendlyTag = FriendlyLevel.Neutral;
- SetDefaultEvent(AI_DoRandomRelex);
- }
- }
-
-
-
- }
