到现在为止,我把animator的使用方式总结为三种:
1.单线连接,每两个动画两两连接在一起。使用bool值或者是trriger控制。这种情况,适用于动画状态比较少,比较简单的逻辑控制,只需要在合适的时机进行setbool操作即可。
2.使用Anystate进行所有状态的链接,适用于,比如只有站立,或者是只有攻击朝向八个方向之类的动画切换
3.通过融合树。和状态机代码的结合,达到对方向和人物的动画行为状态的分别控制,互不干扰并且比较简单
然后是分享一部分FSM状态机代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; public abstract class DD_FSMBase { protected Animator animator; protected Animator anieffect; public abstract void EnterState(); public abstract void LeaveState(); public abstract void ChangeState(); public abstract void Updata(); } public class DD_FSMManger { DD_FSMBase[] AllStates; int Statetmp ; byte Tmcount = 0; byte CuteState; public DD_FSMManger(byte length) { AllStates = new DD_FSMBase[length]; CuteState=0; Statetmp = -1; } public void AddState(DD_FSMBase State) { if (Tmcount < AllStates.Length) { AllStates[Tmcount] = State; Tmcount++; } } public void ChangeState(byte index) { if (Statetmp != -1) { AllStates[CuteState].LeaveState(); } AllStates[index].EnterState(); CuteState = index; Statetmp = CuteState; } public void UpdateState() { if (Statetmp != -1) { AllStates[CuteState].Updata(); } } }
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class DD_PeolpleQian : DD_FSMBase { public DD_PeolpleQian(Animator tmpani, Animator effani) { animator = tmpani; anieffect = effani; } public override void ChangeState() { // throw new NotImplementedException(); } float tmpCount; bool isplaying = false; public override void EnterState() { // throw new NotImplementedException(); animator.SetFloat("People", (float)(DD_PlayerCtrl.DD_AnimationStates.Qian)); anieffect.SetInteger("Effect", (int)DD_PlayerCtrl.DD_AnimationStates.Qian); tmpCount = 0; isplaying = true; } public override void LeaveState() { // throw new NotImplementedException(); isplaying = false; } public override void Updata() { } } public class DD_PeolpleQianRight : DD_FSMBase { public DD_PeolpleQianRight(Animator tmpani, Animator effani) { animator = tmpani; anieffect = effani; } public override void ChangeState() { } public override void EnterState() { animator.SetFloat("People", (float)(DD_PlayerCtrl.DD_AnimationStates.RightQian)); anieffect.SetInteger("Effect", (int)DD_PlayerCtrl.DD_AnimationStates.RightQian); } public override void LeaveState() { } public override void Updata() { } } public class DD_PeolpleRight : DD_FSMBase { public DD_PeolpleRight(Animator tmpani, Animator effani) { animator = tmpani; anieffect = effani; } public override void ChangeState() { // throw new NotImplementedException(); } float tmpCount; bool isplaying = false; public override void EnterState() { // throw new NotImplementedException(); animator.SetFloat("People", (float)(DD_PlayerCtrl.DD_AnimationStates.Right)); anieffect.SetInteger("Effect", (int)DD_PlayerCtrl.DD_AnimationStates.Right); tmpCount = 0; isplaying = true; } public override void LeaveState() { // throw new NotImplementedException(); isplaying = false; } public override void Updata() { } } public class DD_PeolpleRightBack : DD_FSMBase { public DD_PeolpleRightBack(Animator tmpani, Animator effani) { animator = tmpani; anieffect = effani; } public override void ChangeState() { // throw new NotImplementedException(); } float tmpCount; bool isplaying = false; public override void EnterState() { // throw new NotImplementedException(); animator.SetFloat("People", (float)(DD_PlayerCtrl.DD_AnimationStates.RightBack)); anieffect.SetInteger("Effect", (int)DD_PlayerCtrl.DD_AnimationStates.RightBack); tmpCount = 0; isplaying = true; } public override void LeaveState() { // throw new NotImplementedException(); isplaying = false; } public override void Updata() { } } public class DD_PeolpleBack : DD_FSMBase { public DD_PeolpleBack(Animator tmpani, Animator effani) { animator = tmpani; anieffect = effani; } public override void ChangeState() { } float tmpCount; bool isplaying = false; public override void EnterState() { animator.SetFloat("People", (float)(DD_PlayerCtrl.DD_AnimationStates.Back)); anieffect.SetInteger("Effect", (int)DD_PlayerCtrl.DD_AnimationStates.Back); tmpCount = 0; isplaying = true; } public override void LeaveState() { isplaying = false; } public override void Updata() { } } public class DD_PeolpleLeftBack : DD_FSMBase { public DD_PeolpleLeftBack(Animator tmpani, Animator effani) { animator = tmpani; anieffect = effani; } public override void ChangeState() { } float tmpCount; bool isplaying = false; public override void EnterState() { animator.SetFloat("People", (float)(DD_PlayerCtrl.DD_AnimationStates.LeftBack)); anieffect.SetInteger("Effect", (int)DD_PlayerCtrl.DD_AnimationStates.LeftBack); tmpCount = 0; isplaying = true; } public override void LeaveState() { isplaying = false; } public override void Updata() { } } public class DD_PeolpleLeft : DD_FSMBase { public DD_PeolpleLeft(Animator tmpani, Animator effani) { animator = tmpani; anieffect = effani; } public override void ChangeState() { } float tmpCount; bool isplaying = false; public override void EnterState() { animator.SetFloat("People", (float)(DD_PlayerCtrl.DD_AnimationStates.Left)); anieffect.SetInteger("Effect", (int)DD_PlayerCtrl.DD_AnimationStates.Left); tmpCount = 0; isplaying = true; } public override void LeaveState() { isplaying = false; } public override void Updata() { } } public class DD_PeolpleLeftQian : DD_FSMBase { public DD_PeolpleLeftQian(Animator tmpani,Animator effani) { animator = tmpani; anieffect = effani; } public override void ChangeState() { } float tmpCount; bool isplaying = false; public override void EnterState() { animator.SetFloat("People", (float)(DD_PlayerCtrl.DD_AnimationStates.LeftQian)); anieffect.SetInteger("Effect", (int)(DD_PlayerCtrl.DD_AnimationStates.LeftQian)); tmpCount = 0; isplaying = true; } public override void LeaveState() { isplaying = false; } public override void Updata() { } }
using UnityEngine; using System.Collections; public class DD_PlayerCtrl { public enum DD_AnimationStates { Qian, RightQian, Right, RightBack, Back, LeftBack, Left, LeftQian, Max } /// <summary> /// 这个人 /// </summary> private GameObject player; public GameObject Player { get { return player; } set { player = value; } } /// <summary> /// 动画控制 /// </summary> private Animator ani; public Animator Ani { get { return ani; } set { ani = value; } } /// <summary> /// 移动速度 /// </summary> private float playerSpeed; public float PlayerSpeed { get { return playerSpeed; } set { playerSpeed = value; } } /// <summary> /// 冲刺距离 /// </summary> private float distance; public float Distance { get { return distance; } set { distance = value; } } public DD_FSMManger Fsmmanager { get { return fsmmanager; } set { fsmmanager = value; } } public bool IsAttackMove { get { return isAttackMove; } set { isAttackMove = value; } } public Vector3 InitPos { get { return initPos; } set { initPos = value; } } public Vector3 TmpTar { get { return tmpTar; } set { tmpTar = value; } } public Animator Effectani { get { return effectani; } set { effectani = value; } } public bool IsBeDeamage { get { return isBeDeamage; } set { isBeDeamage = value; } } public bool Isdown { get { return isdown; } set { isdown = value; } } DD_FSMManger fsmmanager; /// <summary> /// 是否移动 /// </summary> private bool isAttackMove = false; /// <summary> /// 开始移动的位置 /// </summary> private Vector3 initPos; private Vector3 tmpTar; private Animator effectani; private GameObject Chong; private bool isBeDeamage = true; private TrailRenderer trail; private Rigidbody2D rigi; private bool isdown = false; /// <summary> /// 初始化 /// </summary> public void Init() { Player = GameObject.Find("Player1"); trail = player.GetComponent<TrailRenderer>(); trail.enabled = false; rigi = player.GetComponent<Rigidbody2D>(); Chong = GameObject.Find("Chong"); effectani = Chong.GetComponent<Animator>(); Ani = Player.GetComponent<Animator>(); Fsmmanager = new DD_FSMManger((byte)DD_AnimationStates.Max); DD_PeolpleQian qian = new DD_PeolpleQian(ani, effectani); Fsmmanager.AddState(qian); DD_PeolpleQianRight rightqian = new DD_PeolpleQianRight(ani, effectani); Fsmmanager.AddState(rightqian); DD_PeolpleRight right = new DD_PeolpleRight(ani, effectani); Fsmmanager.AddState(right); DD_PeolpleRightBack rightback = new DD_PeolpleRightBack(ani, effectani); Fsmmanager.AddState(rightback); DD_PeolpleBack back = new DD_PeolpleBack(ani, effectani); Fsmmanager.AddState(back); DD_PeolpleLeftBack leftback = new DD_PeolpleLeftBack(ani, effectani); Fsmmanager.AddState(leftback); DD_PeolpleLeft left = new DD_PeolpleLeft(ani, effectani); Fsmmanager.AddState(left); DD_PeolpleLeftQian leftqian = new DD_PeolpleLeftQian(ani, effectani); Fsmmanager.AddState(leftqian); Chong.transform.localScale = Vector3.zero; } public DD_PlayerCtrl(float tmSpeend, float tmDis) { PlayerSpeed = tmSpeend; distance = tmDis; } /// <summary> /// 人物攻击的冲撞移动 /// </summary> public void Move() { tmpTar.z = 0; player.transform.localPosition = Vector3.Lerp(player.transform.localPosition, initPos + TmpTar.normalized * distance, 0.2f); if (Vector3.Distance(player.transform.localPosition, initPos + TmpTar.normalized * distance) < 0.1f) { isAttackMove = false; } } /// <summary> /// 开始跑 /// </summary> public void StartRun() { ani.SetBool("Run", true); } /// <summary> /// 跑停止恢复站立 /// </summary> public void StopRun() { ani.SetBool("Run", false); } /// <summary> /// 开始攻击 /// </summary> public void StartAttack() { DD_StateManager.Instance.Gamepanel.Lianji.transform.localScale = Vector3.zero; trail.enabled = true; Chong.transform.localScale = Vector3.one; DD_TegCtrl.InStance.Ismove = false; ani.SetBool("Attack", true); if (DD_GameCtrl.Instance.Gamedata.Count > DD_GameCtrl.Instance.Gamedata.Max) DD_GameCtrl.Instance.Gamedata.Max = DD_GameCtrl.Instance.Gamedata.Count; DD_GameCtrl.Instance.Gamedata.Count = 0; } /// <summary> /// 暂停攻击 /// </summary> public void StopAttack() { trail.enabled = false; isBeDeamage = true; DD_TegCtrl.InStance.Ismove = true; Chong.transform.localScale = Vector3.zero; ani.SetBool("Attack", false); } public void SetPos() { InitPos = player.transform.localPosition; TmpTar = DD_TegCtrl.InStance.TmVetx; if (DD_TegCtrl.InStance.TmVetx == Vector3.zero) tmpTar = Vector3.up; } public void Dead() { DD_AudioManager.Instance.Play("Dead"); if (DD_StateManager.Instance.NowState != DD_State.Defeat) { DD_StateManager.Instance.StateExit(); DD_StateManager.Instance.ChangeState(DD_State.Defeat); Time.timeScale = 0; } } /// <summary> /// 人物掉下 /// </summary> public void Down() { trail.enabled = false; player.transform.Translate(Vector3.down * 0.05f, Space.World); player.transform.localScale -= new Vector3(0.005f, 0.005f, 0); if (player.transform.localScale.x <= 0) { player.transform.localScale = Vector3.zero; Dead(); Isdown = false; } } /// <summary> /// 持续的行为 /// </summary> public void OnUpdate() { if (Isdown) { Down(); } if (isAttackMove) { Move(); } if (!isBeDeamage) { for (int i = 0; i < DD_MonsterManager.Instance.Allmons.Count; i++) { if (Vector3.Distance(DD_MonsterManager.Instance.Allmons[i].MosterObj.transform.localPosition, player.transform.transform.localPosition) < 0.3f && DD_MonsterManager.Instance.Allmons[i].IsDead != true) { DD_MonsterManager.Instance.Allmons[i].IsDead = true; DD_AudioManager.Instance.Play("Fly"); DD_PoolManager.Instance.ReciveAObjectBy(DD_MonsterManager.Instance.Allmons[i].Effect.gameObject); DD_GameCtrl.Instance.Gamedata.Kill++; DD_GameCtrl.Instance.Gamedata.Count++; if (DD_GameCtrl.Instance.Gamedata.Count >= 2) DD_StateManager.Instance.Gamepanel.Lianji.transform.localScale = Vector3.one; DD_GameCtrl.Instance.Gamedata.Allmoney += DD_MonsterManager.Instance.Allmons[i].Price; } } } } }