HTFramework框架使用手册(三) FSM有限状态机

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq992817263/article/details/86073351

FSM模块简介

FSM有限状态机用于模拟一切可以抽象为有限状态机结构的业务逻辑,类似于角色动画、怪物AI、任意有独立逻辑的个体等。

使用FSM

自定义状态

使用FSM前,必须自定义状态,任何自定义状态,可用于任何FSM使用,自定义状态类必须满足以下条件:
1.继承至FiniteState
2.标记特性FiniteStateName
推荐使用快捷创建方式:
Project界面右键 -> Create -> HTFramework -> FiniteState Script
在这里插入图片描述
如下图,我自定义了一个名为IdleState的状态:(相应的实现函数将在此状态的对应时机调用)

/// <summary>
/// 闲置状态
/// </summary>
[FiniteStateName("Player/闲置")]
public class IdleState : FiniteState
{
	/// <summary>
	/// 初始化
	/// </summary>
    public override void OnInit()
    {

    }

	/// <summary>
	/// 进入状态
	/// </summary>
    public override void OnEnter()
    {
        
    }
    
	/// <summary>
	/// 离开状态
	/// </summary>
    public override void OnLeave()
    {
        
    }

	/// <summary>
	/// 切换状态的动机
	/// </summary>
    public override void OnReason()
    {
       
    }

	/// <summary>
	/// 状态帧刷新
	/// </summary>
    public override void OnUpdate()
    {

    }

	/// <summary>
	/// 状态终结
	/// </summary>
    public override void OnTermination()
    {
       
    }
}

创建新的FSM

选中任意物体,为其添加FSM脚本后,其便已作为一个单独的有限状态机存在,这里为Player添加一个FSM脚本:
Component -> HTFramework -> FSM
在这里插入图片描述

为FSM附加状态

修改FSMNamePlayer001,注意名字不能重复!
点击下方的Add State按钮,可以附加我们创建的自定义状态到此FSM:(注意:附加状态时的路径为FiniteStateName特性指定的路径)
在这里插入图片描述
FSM存在至少一个状态后,会自动指定第一个附加的状态为初始状态,可以直接点击Set Default按钮重新设置初始状态:
在这里插入图片描述

为FSM使用自定义数据

很多时候,不同的FSM拥有不同的数据,为FSM指定自定义数据是一个不错的选择。
如何使用自定义数据类:新建类,使其继承至FSMData
如下,新建Player的数据类PlayerData

public class PlayerData : FSMData
{
    //攻击力
    public int AttackPower;
    //防御力
    public int DefensePower;
    //速度
    public float Speed;

    public override void OnInit()
    {
        
    }
}

然后直接在PlayerFSM面板为其指定数据类为PlayerData
在这里插入图片描述
指定后,状态机Player001内的所有状态都将拥有一个共同的数据类对象PlayerData,访问数据的方法非常简单,如下:

[FiniteStateName("Player/攻击")]
public class AttackState : FiniteState
{
	/// <summary>
	/// 初始化
	/// </summary>
    public override void OnInit()
    {
        // OwnStateMachine 为此状态当前所属状态机
        PlayerData data = OwnStateMachine.CurrentData as PlayerData;
        GlobalTools.LogInfo("攻击力:" + data.AttackPower);
        GlobalTools.LogInfo("防御力:" + data.DefensePower);
        GlobalTools.LogInfo("速度:" + data.Speed);
    }
}

切换状态

FSM启动后将会进入默认状态,此时将切换到其他状态的动机写到OnReason方法内是一个明智的决定,在判断时机成熟时,切换状态的方法如下:

	/// <summary>
	/// 切换状态的动机
	/// </summary>
    public override void OnReason()
    {
        //开始攻击
        if (IsAttack)
        {
            OwnStateMachine.SwitchState<AttackState>();
        }
    }

也可以在状态机外部切换状态:

	void Update ()
    {
        //开始攻击
        if (IsAttack)
        {
            // GetFSMByName 通过名称获取状态机
            Main.m_FSM.GetFSMByName("Player001").SwitchState<AttackState>();
        }
    }

运行时动态附加状态

FSM支持运行时动态附加状态,比如角色002是一个NPC,其在初始时不具备攻击状态AttackState,之后由于剧情需要为其开放攻击模式,则可以动态为其附加AttackState

        FSM fsm = Main.m_FSM.GetFSMByName("Player001");
        fsm.AppendState<AttackState>();
        fsm.SwitchState<AttackState>();

运行时动态终结状态

FSM支持运行时动态终结状态,比如角色002由于被主角打败已经彻底失去了战斗力,此时可以直接终结其攻击状态AttackState,则后续其所有妄图攻击的请求都会被阻断:

        FSM fsm = Main.m_FSM.GetFSMByName("Player001");
        fsm.TerminationState<AttackState>();

猜你喜欢

转载自blog.csdn.net/qq992817263/article/details/86073351