FSM有限状态机架构

      首先我们应该定义一个状态基类FSMBase,里面有一些动画状态的基本行为,比如动画状态的进入,持续,离开等,然后因为人物并不是只有一个状态,所以我们应该建立一个状态管理器来管理状态,里面应该定义一些方法,比如 我们应该定义一些状态的共同逻辑,比如对状态进行存储,添加状态AddState,状态间跳转的方法ChangeState(进入当前的动画状态时,应该离开上一个动画状态,从而保证每一帧处理的都是当前状态的逻辑)。
      然后抽象出相应的状态类,即每一个状态都是一个类,如果增添状态,则需要再次定义相应的状态类并继承,每一个状态类都只写与自身相关的逻辑。
     档具体的调用时,我们可以通过枚举,将状态添加到状态管理类里,然后如果需要跳转,就应该在状态类里设置一个代理,将需要改变的状态传回至FSMManager管理类的ChangeState方法里,进行跳转,而不是直接进行跳转,这样就大大减少了各个状态之间的耦合性和状态的扩展性。

代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class FSMBase
{
    public Animator animator;
    public abstract void OnEnter();
    public abstract void OnLeave();
    public abstract void UpDate();

}

public class FSMManager
{
    FSMBase[] allState;
    byte curState;
    short stateIndex;
    public FSMManager (byte count)
    {
        allState = new FSMBase[count];
        curState = 0;
        stateIndex = -1;
    }
    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="tmpBase">Tmp base.</param>
    public void AddState(FSMBase tmpBase)
    {
        if (curState<allState.Length)
        {
            allState[curState] = tmpBase;
            curState++;
        }
    }
    /// <summary>
    /// 状态跳转
    /// </summary>
    /// <param name="index">Index.</param>
    public void ChangeState(byte index)
    {
        if (stateIndex!=-1)
        {
            allState[curState].OnLeave();
        }
        stateIndex = curState;
        allState[index].OnEnter();
        curState = index;
    }

    public void Update()
    {
        if (stateIndex!=-1)
        {
            allState[curState].UpDate();
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum AnimalState
{
    Idle,
    Attack,
    Walk,
    Jump,
    Max

}
public class PlayerController : MonoBehaviour {

    FSMManager fsmManger;
    private void Start()
    {
        fsmManger = new FSMManager((byte)AnimalState.Max);
        Animator ani = GetComponent<Animator>();
        PlayerIdle tmpIdle = new PlayerIdle(ani);
        fsmManger.AddState(tmpIdle);
        PlayerAttack tmpAttack = new PlayerAttack(ani);
        fsmManger.AddState(tmpAttack);
        PlayerWalk tmpWalk= new PlayerWalk(ani);
        fsmManger.AddState(tmpWalk);
        PlayerJump tmpJump = new PlayerJump(ani);
        fsmManger.AddState(tmpJump);
    }
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            fsmManger.ChangeState((byte)AnimalState.Walk);
        }
    }
}

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public delegate void ChangeDelegate(byte index);

public class PlayerIdle : FSMBase
{
    public PlayerIdle(Animator tmpAnimal)
    {
        this.animator = tmpAnimal;
    }
    public override void OnEnter()
    {
        this.animator.SetInteger("StateIndex",1);
    }

    public override void OnLeave()
    {
        
    }

    public override void UpDate()
    {
        
    }
}

public class PlayerAttack : FSMBase
{
	public PlayerAttack(Animator tmpAnimator)
	{
		this.animator = tmpAnimator;
	}
	public override void OnEnter()
	{
		this.animator.SetInteger("StateIndex", 2);
	}

	public override void OnLeave()
	{

	}

	public override void UpDate()
	{

	}
}
public class PlayerWalk : FSMBase
{
    public PlayerWalk(Animator tmpAnimator)
    {
        this.animator = tmpAnimator;
    }
    public override void OnEnter()
    {
        this.animator.SetInteger("StateIndex",3);
    }

    public override void OnLeave()
    {
        
    }

    public override void UpDate()
    {
        
    }
}

public class Jump : FSMBase
{
    ChangeDelegate changeIdle;
	public Skill1(Animator tmpAnimal,ChangeDelegate tmpDlegate)
	{
		this.animator = tmpAnimal;
        changeIdle = tmpDlegate;
	}
	float timer = 0;
	bool isPlayFinish;
	public override void OnEnter()
	{
		this.animator.SetInteger("StateIndex", 4);
		timer = 0;
		isPlayFinish = false;
	}

	public override void OnLeave()
	{
		timer = 0;
		isPlayFinish = false;
	}

	public override void UpDate()
	{
		timer += Time.deltaTime;
		if (timer > 0.28f && !isPlayFinish)
		{
			isPlayFinish = true;

			//do samething
		}
		if (timer > 1)
		{
			timer = 0;
			isPlayFinish = false;
			changeIdle((byte)AnimalStateSkill.Idle);
		}
	}
}

public void ChangeState(byte index)
	{
		fsmManger.ChangeState(index);
	}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值