高级状态机创建

自己动手造一个状态机 大厂常用的状态机实现,还不赶紧学起来! 阅读详情

首先知道简单状态机

这种方法中我们把状态和条件判断都集中在一个类里面,代码量冗多,不方便管理,很容易搞混

高级状态机则是通过把状态,状态引用,角色引用分离,是代码看起来十分清晰;


首先先定义一个抽象状态基类(FSMState),枚举切换状态的条件,状态若干;新建一个字典《看见什么条件,切换为什么状态》;添加字典是必须判断输入是否规范,增加程序的 健壮性。比如说条件是否为空,状态是否为空,条件是否已经存在。再定义一个类通过传条件获取当前的状态。接着定义虚方法进入状态之前和状态之后,定义抽象方法状态进行时和条件判断,最后引用一个状态机类(FSMSystem),在构造函数赋值;

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

public enum Transition
{
    NullTransition=0,
    SeePlayer,
    LostPlayer,
}
public enum StateID
{
    NullStateId=0,
    Patrol,
    Chase,
}

public abstract class FSMState{


    protected StateID stateID;
    public StateID ID { get { return stateID; } }                    //返回stateID
    public Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();
    protected FSMSystem fsm;                                        //引用的FSMSystem

    public FSMState(FSMSystem fsm)                                  //先调用构造函数更新引用的FSMSystem;
    {
        this.fsm = fsm;
    }



    public void AddTransition(Transition tran,StateID id)         //添加转化条件(构造)
    {
        if (tran==Transition.NullTransition)
        {
            Debug.LogError("不允许条件为空");return;
        }
        if (id == StateID.NullStateId)
        {
            Debug.LogError("不允许状态为空"); return;
        }
        if (map.ContainsKey(tran))
        {
            Debug.LogError("条件已经存在"); return;
        }
        map.Add(tran,id);
    }


    public void DeleteTransition(Transition tran,StateID id)
    {
        if (tran == Transition.NullTransition)
        {
            Debug.LogError("不允许条件为空"); return;
        }
        if (map.ContainsKey(tran)==false)
        {
            Debug.LogError("条件不存在"); return;
        }
        map.Remove(tran);
    }

    public StateID GetState(Transition tran)
    {
        if (map.ContainsKey(tran))
        {
            return map[tran];
        }
        return StateID.NullStateId;
    }

    public virtual void BeforeEnter() { }
    public virtual void AfterExit() { }
    public abstract void Act(GameObject npc);                 //进入状态之时(抽象类每个子类不同必须重写)
    public abstract void Reason(GameObject npc);              //判断转换条件,条件机



    // Use this for initialization
    void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}


定义一个状态机类(FSMSystem),为不用遍历采用字典《状态,状态抽象类》,变量有,当前状态和当前 抽象状态基类

函数一:通过传抽象状态基类为字典赋值

函数二:执行条件(如果条件没报错的话),赋值当前状态和当前 抽象状态基类。

函数三:传值gameobject给update;时刻调用状态进行时和条件判断

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

public class FSMSystem  {                                                                    //状态机

    private Dictionary<StateID, FSMState> states = new Dictionary<StateID, FSMState>();     //状态,条件状态

    private StateID currentStateID;         //当前状态
    private FSMState currentState;          //当前状态和条件

    public void AddState(FSMState s)
    {
        if (s==null)
        {
            Debug.LogError("FSM不能为空");return;
        }
        if (currentState ==null)
        {
            currentState = s;
            currentStateID = s.ID;
        }
        if (states.ContainsKey(s.ID))
        {
            Debug.LogError("状态存在"+s.ID); return;

        }
        states.Add(s.ID,s);
    }
    public void DeleState(StateID id)
    {
        if (id==StateID.NullStateId)
        {
            Debug.LogError("无法删除空状态");return;
        }
        if (states.ContainsKey(id)==false)
        {
            Debug.LogError("无法删除不存在的状态"+id);
        }
        states.Remove(id);
    }

    public void PerformTransition(Transition tran)              //传进来一个条件,执行条件
    {
        if (tran==Transition.NullTransition)
        {
            Debug.LogError("无法执行空的转换条件");return;
        }
        StateID id= currentState.GetState(tran);                //通过条件获取ID
        if (id==StateID.NullStateId)
        {
            Debug.LogError("该条件没有对应的状态");return;
        }
        if (states.ContainsKey(id)==false)                      //当前状态机字典里是否有这个状态
        {
            Debug.LogError("状态机不存在这个状态"); return;
        }
        FSMState state = states[id];                            //把状态和条件赋值给 局部变量
        currentState.AfterExit();                               //播放状态离开部分
        currentState = state;                                   //赋值给当前条件和状态
        currentStateID = id;                                    //赋值给当前状态
        currentState.BeforeEnter();                             //播放状态进入之前
    }

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	public void Update (GameObject npc) {
        currentState.Act(npc);                                  //调用当前状态的ACT
        currentState.Reason(npc);
	}
}


定义巡逻类,追寻类;重写构造方法,状态进行时和条件判断

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

public class PatrolState :  FSMState{

    public List<Transform> path=new List<Transform>() ;
    public int index = 0;
    public Transform player;
    public PatrolState(FSMSystem fsm) : base(fsm)                               //那么子类也要传一个FSM用于更新父类fsm
    {
        player = GameObject.Find("Play").transform;
        stateID = StateID.Patrol;                                              //继承并修改父类参数
        Transform Path1 = GameObject.Find("Path").transform;
        Transform[] children = Path1.GetComponentsInChildren<Transform>();    //这个位置组包含Path的位置
        foreach (Transform child in children)
        {
            if (child!=Path1)
            {
                path.Add(child);
            }
        }                
    }

    public override void Act(GameObject npc)                                //覆盖重写
    {
        npc.transform.LookAt(path[index].position);
        npc.transform.Translate(Vector3.forward*Time.deltaTime*3);
        if (Vector3.Distance(npc.transform.position,path[index].position)<1)
        {
            index++;
            index %= path.Count;
        }
    }

    public override void Reason(GameObject npc)                             
    {
        if (Vector3.Distance(player.position,npc.transform.position)<3)
        {
            fsm.PerformTransition(Transition.SeePlayer);
        }
        //throw new NotImplementedException();
    }

    // Use this for initialization
    void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Chase : FSMState {

    private Transform player;
    public Chase(FSMSystem fsm) : base(fsm)
    {
        stateID = StateID.Chase;
        player = GameObject.Find("Play").transform;
    }

    public override void Act(GameObject npc)
    {
        npc.transform.LookAt(player.position);
        npc.transform.Translate(Vector3.forward*Time.deltaTime*2);
    }

    public override void Reason(GameObject npc)
    {
        if (Vector3.Distance(player.position, npc.transform.position) > 6)
        {
            fsm.PerformTransition(Transition.LostPlayer);
        }
        //throw new NotImplementedException();
    }

    // Use this for initialization
    void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}



定义敌人类

  1. new一个状态机,初始化,新建一个状态机,见一个巡逻类,赋值状态机给构造函数往字典《看见什么条件,切换为什么状态》加“看见敌人条件”,“追寻状态”。调用状态机添加巡逻状态的函数。
  2. 新建一个状态机,见一个追寻类,赋值状态机给构造函数往字典《看见什么条件,切换为什么状态》加“丢失敌人条件”,“巡逻状态”。调用状态机添加追寻状态的函数。
  3. update给状态机update添加this.gameobject'

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

public class enemy : MonoBehaviour {

    public FSMSystem fsm;

	// Use this for initialization
	void Start () {
        InitFSM();
	}
    void InitFSM()
    {
        fsm = new FSMSystem();

        FSMState patrolState = new PatrolState(fsm);
        patrolState.AddTransition(Transition.SeePlayer,StateID.Chase);
        fsm.AddState(patrolState);

        FSMState ChaseState = new Chase(fsm);
        ChaseState.AddTransition(Transition.LostPlayer, StateID.Patrol);

        fsm.AddState(ChaseState);


    }

    // Update is called once per frame
    void Update () {
        fsm.Update(this.gameObject);
	}
}


qt中状态机详细使用方法和教程 信号转换(SignalTransition):基于信号的转换。条件转换(ConditionTransition):基于条件的转换。// 信号转换:当按钮点击时从state1切换到state2// 条件转换:当满足某个条件时从state2切换到state1});Qt状态机是一个强大的工具,可以帮助你管理复杂的逻辑和状态转换。通过定义状态、转换和动作,你可以轻松实现复杂的交互逻辑。希望这个教程能帮助你快速上手Qt状态机! 阅读详情

相关推荐

Unreal Engine开发:角色动画与状态机_动画状态机:使用状态机管理不同动画状态

动画状态机(Animation State Machine)是一种用于管理角色动画状态的工具。通过状态机,可以将角色的动画状态(如行走、奔跑、跳跃、攻击等)组织成一个图形化的工作流,每个状态可以包含一个或多个动画序列。状态机不仅使动画管理更加直观,还可以通过状态之间的过渡来实现不同动画之间的平滑切换。通过使用动画状态机,可以有效地管理和控制角色的动画状态,使角色的动画更加自然和流畅。在实际开发中,结合C++和动画蓝图,可以实现复杂而高效的动画系统。动画状态机:用于组织和管理不同动画状态。状态之间的过渡。

chenlz2007的博客 1282

高级有限状态机

简单有限状态机可直接使用switch case语句进行对状态的管理 这里介绍一种高级有限状态机,其框架大致如下 其中FSMState为状态的基类,包含两种枚举类型的变量StateID(状态的ID),Transition(状态的转换条件),FSMSystem用于管理FSMState,而每一个Enemy都拥有一个FSMSystem。 敌人状态类 *****************************************************/ using System.C...

jhgsdcfghjkl的博客 318

Cocos Creator引擎开发:动作效果与角色动画_动画控制器与状态机

通过本节的学习,我们了解了如何在Cocos Creator中使用动画控制器和状态机来实现角色的动画效果。动画控制器允许我们管理和控制角色的不同动画状态,而状态机则帮助我们定义这些状态之间的转换逻辑。我们还学习了如何通过动画参数、混合树和状态机事件来实现更复杂的动画效果,并提供了优化和调试的技巧。希望这些内容能帮助你在动作游戏开发中更好地实现角色动画。通过本节的学习,我们深入了解了如何在Cocos Creator中使用动画控制器和状态机来实现复杂角色动画和动作效果。

chenlz2007的博客 1333

如何设计一个状态机!

1、什么是状态机1.1 什么是状态先来解释什么是“状态”( State )。现实事物是有不同状态的,例如一个自动门,就有 open 和 closed 两种状态。我们通常所说的状态机是有限状态机,也就是被描述的事物的状态的数量是有限个,例如自动门的状态就是两个 open 和 closed 。状态机,也就是 State Machine ,不是指一台实际机器,而是指一个数学模型。说白了,一般就是指一张状...

架构文摘 6181

Unreal Engine开发:角色动画与状态机_动画蓝图的高级用法

通过本节的学习,我们已经掌握了动画蓝图的高级用法,包括状态机、混合空间、动画曲线、动画事件、动态混合、动画层和动画通知。这些技术不仅使角色动画更加复杂和逼真,还提高了动画管理的有序性和可维护性。在实际开发中,结合调试和优化技术,我们可以确保动画效果的正确性和性能的高效性。希望这些内容对你在动画蓝图的使用上有所帮助,让你能够创建出更加精彩和流畅的角色动画。

chenlz2007的博客 856

Godot引擎开发:动作系统设计_动画节点与状态机

通过使用动画节点和状态机,我们可以轻松地创建出复杂且高度互动的角色动画系统。Blend Tree和State Machine提供了丰富的工具和方法,帮助开发者管理动画状态和过渡。在实际开发中,合理配置动画参数和过渡条件,以及优化状态机,都是确保动画系统高效运行的关键。希望本节内容能帮助你更好地理解和应用Godot引擎中的动画节点和状态机。通过使用动画节点和状态机,我们可以创建出复杂且高度互动的角色动画系统。

chenlz2007的博客 976

Spring Statemachine使用入门

1、编程式 下面以官网的示例稍加改造举例来体会一下Spring Statemachine使用。 添加下面maven坐标到pom中。 <dependencies> <dependency> <groupId>org.springframework.statemachine</groupId> <ar...

通往神秘的道路的专栏 1928

状态机思想编写led+key程序(C8051F120)

状态机思想编写led+key程序(C8051F120)

状态机按键写法

个人笔记

weixin_47810364的博客 563

晶体管的 栅极gate 材料选用 多晶硅polysilicon,并采用 自对准工艺 self-aligned IC后端版图 【VLSI】

本文为了解决为什么要使用多晶硅作栅极触点的问题,先介绍了MOS管的工作原理是通过栅极上所加的电压控制漏极与源极之间电流,然后解释了栅极的材料为什么选用多晶硅,然后介绍了晶体管里栅极的自对准工艺(Self-Aligned Gate )。

Jie_MSD的博客 1万+

华为防火墙USG6000系列多ISP上网(通过WEB界面设置)

华为防火墙多ISP上网,内网分区上网。内网多网段不同上网方式。

daxihe880的博客 1万+

Qt状态机框架(01):The State Machine Framework【官翻】

文章目录一、前言二、状态机框架中的类三、简单的状态机示例3.1 首先,我们创建状态机和状态:3.2 然后,我们使用QState::addTransition()函数来创建转换:3.3 然后,为QState指定关联对象的属性的值3.4 接下来,我们将状态添加到机器中,设置机器的初始状态:3.4 最后,我们启动状态机:四 、状态进入和退出时的信号五、状态机的结束六、通过分组状态共享转换七、使用历史状态保存和恢复当前状态八、使用并行状态来避免状态的组合爆炸九、检测复合状态已经完成十、无目标转换十一、事件、转换和保

读书笔记 2609

嵌入式常用通信协议 #概述

嵌入式通信协议

AFK3060的博客 2117

SP2010开发和VS2010专家"食谱"--第三章节--高级工作流(3)--创建状态机工作流

到现在我们学习了如何创建顺序工作流(作为列表或网站工作流)。我们也学习了如何添加自定义初始和任务表单到工作流。本文中,我们将创建状态机工作流定义项目审批过程。

NetSuite 张老师 1255

新政下的绿电直连项目经济性分析:模式创新与价值重构

随着全球气候治理与低碳转型进程不断加速,绿电直连作为新能源就近消纳的创新模式,正成为破解新能源消纳瓶颈、规避碳关税壁垒的核心路径。2025年9月,国家发展改革委、国家能源局发布《关于完善价格机制促进新能源发电就近消纳的通知》(1192号文),为绿电直连项目的经济性分析与效益测算提供了明确的政策依据。本文将基于新政框架,深入解析绿电直连项目的经济性影响因素、盈利模式与优化路径,并结合案例与量化模型,为项目投资决策提供系统参考。

getusushu的博客 140

【LSTM回归预测】attention机制LSTM时间序列回归预测【含Matlab源码 1992期】

attention机制LSTM时间序列回归预测 完整的代码,方可运行;可提供运行操作视频!适合小白!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 2591

使用python3描述状态机

这段代码定义了一个简单的状态机,管理从“idle”状态到“running”状态,再到“completed”状态的转换,并可以重置回“idle”状态。状态机是一个数学模型,用于描述系统在不同状态下的行为以及如何在这些状态之间转换。库是一个用于创建有限状态机的 Python 库。以下是一个简单的状态机示例,使用Python中的。

言之。 1万+

Openclaw错误分析与解决方案之:All models are temporarily rate-limited. Please try again in a few minutes

Openclaw错误分析与解决方案之: All models are temporarily rate-limited. Please try again in a few minutes.

多媒体编程、网络编程、系统编程、网络安全编程、驱动编程 1619

Unity动画知识之二:Animator动画状态机

文/拉撒路   上次我们讲过Unity游戏动画从入门到住院,今天我们来讲一下动画状态机。   好了,现在我们已经成功的导入了动画。接下来要玩的东西就很装13啦。因为大部分动画师是用不到这家伙的,需要掌握这个技能的,至少也是动画组长级别了。嗯。。。一个组只有你一个动画的,闭嘴!给你个同情的眼神。   这个装叉的东西就是动画状态机   嘛~肯定有不明真相的吃

qq_35250079的博客 1045

【WRF-FDDA】观测 Obs nudging 的配置与使用说明(中)

WRF-FDDA

WW、forever的博客 281

cesium 实现经纬线绘制和经纬度标注

废话不对数直接上线效果图及代码 1.效果图 2.实现代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=

一碗老面的博客 2569

Qt状态机框架

The State Machine Framework 状态机框架提供了用于创建和执行状态图的类。概念和符号是基于Harel的Statecharts: A visual formalism for complex systems,它也是UML状态图的基础。状态机执行的语义是基于State Chart XML (SCXML).的。 状态图提供了图解了系统对于刺激的反应的建模。这是通过定义系统

hai200501019的专栏 3658

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

vivado ila 使用高级触发器模式

vivado ila 使用高级触发器模式

cckkppll的博客 5048

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

状态机--状态机6,关于战斗兵种的状态机初步优化和状态设计

先提供下载地址:http://pan.baidu.com/s/1kTqsD6n 解压缩出来直接双击exe就可以运行了,代码在src里面,目录是这样的 分成6个版本,高层模块的调用在scenes中的MainScene.lua中,代码可见 版本控制在onEnter()函数中,按对应的字母键调用不同的函数进行状态切换 最后一个版本的运行结果如下:

zlQQhs(莫落)的专栏 2282

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Qt/C++ Qt状态机框架(QStateMachine)的简明指南

Qt状态机框架提供了创建和执行状态图的类。概念和符号基于Harel的状态图,这也是UML状态图的基础。状态机执行的语义基于状态图XML (SCXML)。

Duran.L的专栏 9395
上一篇: 写一篇关于群组的算法实现(unity)
下一篇: A*寻路
RootTimeYu
博客等级 码龄9年 4粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值