有限动画状态机

到现在为止,我把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;
                }
            }
        }
    }
}