精华内容
下载资源
问答
  • Unity 有限状态机(FSM)的框架结构
    2021-04-18 21:58:02

    前言

    NPC是游戏中很重要的一部分,功能复杂,行为智能的NPC可以给玩家带来更加优秀的游戏体验,我们可以通过对NPC的行为模式的设计来理解有限状态机

    而对于游戏开发者而言,要实现一个功能完备,逻辑清晰的AI状态图可不是一件简单的事情,如果没有前期的完备的设计,以及正确的编程方法,会在开发过程中产生很多难以解决的问题

    一,Switch Case的使用:

    在游戏开发过程中,你想要实现一个NPC的一些功能,比如静止与攻击,当玩家靠近NPCNPC就会攻击玩家,编写一段逻辑代码来实现这样的一个效果:

    if(玩家靠近)
       NPC攻击玩家代码
    if(玩家远离)
       NPC静止代码
    

    NPC行为状态比较简单时,我们可以通过if判断来实现这样的效果


    但是当NPC的状态增加时呢,比如说有静止、攻击、追击、巡逻这些状态时呢,我们所有逻辑在使用if else实现这样的转换就会使得逻辑变得很难理解,这个时候就可以使用Switch case配合枚举 来进行状态的转化:

    public enum State
    {
        idle,
        patrol,
        attact,
        pursuit,
    
    }
    
    
    public class FishRod : MonoBehaviour
    {
    
        State state=new State();
    
        public void Test()
        {
            switch (state)
            {
                case State.idle:
                    //idle状态下的NPC逻辑代码
                    break;
                case State.patrol:
                    //巡逻状态下NPC逻辑代码
                    break;
                case State.attact:
                    //攻击状态下的NPC逻辑代码
                    break;
                case State.pursuit:
                    //追击状态下的NPC逻辑代码
                    break;
               
            }
        }
    
    
    }
    

    很明显,这样逻辑就会清晰很多,只需要在不同状态下修改state对应的枚举类型即可,这样可以将判断代码与执行代码进行分离

    通过Switch case结合枚举可以很好的处理NPC行为状态的逻辑,但是在实际生产中,对于每一种状态的处理也是很复杂,有事使用Switch case会有一定的局限性,使用起来依旧很复杂,这就需要专门的状态管理的设计模式有限状态机来进行逻辑的处理

    为了更好的实现对NPC的行为状态的设计,逐渐产生了有限状态机这样的设计模式,来帮助游戏开发者通过框架层的开发特点进行更为简单的游戏开发

    二、有限状态机

    1、什么是有限状态机

    有限状态机是基于状态模式的一种,首先第一点就是在有限的状态内进行相应状态的切换,而一种状态对应的是一个对象,即通过一个类来实现一个状态,这是有限状态机与Switch Case的主要区别之处

    什么是状态模式:

    • 状态模式是一种设计模式
    • 在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式
    • 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的context 对象

    有限状态机的实现的目的与特点:

    • 意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类

    • 主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。

    • 何时使用:代码中包含大量与对象状态有关的条件语句。

    • 如何解决:将各种具体的状态类抽象出来。

    • 使用场景: 1、行为随状态改变而改变的场景 2、条件、分支语句的代替者

    • 注意事项:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个

    为什么状态不超过五个呢

    • 首先状态太多不好理解,难以记忆,其次超过五个状态一般来说很多状态没有联系
    • 如果超过五个可以使用层次模式,大的状态嵌套小的没有联系状态

    使用有限状态机的优点:

    • 1、封装了转换规则
    • 2、枚举可能的状态,在枚举状态之前需要确定状态种类
    • 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为
    • 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块
    • 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数

    缺点:

    • 1、状态模式的使用必然会增加系统类和对象的个数
    • 2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱
    • 3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

    2,代码实现有限状态机

    第一步,创建一个脚本,定义一个接口IState,用来声明一种状态的运行周期,如果你了解Unity脚本生命周期,很清楚代码三个方法代表的意义,如果你不了解也没有关系,我在下面列出了三个方法的关键用法:

    • OnEnter:可以用来处理变量的初始化、只在进入状态时调用一次的代码模块
    • OnUpdate:用来处理重复调用的代码模块
    • OnExit:在状态退出时执行的代码,同样只执行一次

    接口IState的代码为:

    
    public interface IState
    {
    	 //进入状态时调用一次
         void OnEnter();
    
         //处于状态时,连续调用
         void OnUpdate();
    
          //退出状态时调用一次
         void OnExit();
    
    }
    

    接下来写一个基础的状态类BaseFSM,用来实现状态的定义与切换:

    首先定义一个枚举类型State_Enum作为对象的所有状态,为了代码简洁,本次案例使用IdleRun两种状态来进行有限状态机的实现:

    // BaseFSM脚本
    
    /// <summary>
    /// 状态枚举类型
    /// </summary>
    public enum State_Enum
    {
        idle,
        run
    }
    
    
    

    接下来创建一个新的脚本AllStates两个新的类IdleRun并继承于IState,即创建一个状态的对象,用来实现状态的具体代码:

    //AllStates脚本
    
    /// <summary>
    /// Idle状态
    /// </summary>
    public class Idle: IState
    {
    	private BaseFSM manager; 
    	//构造函数获取刚刚创建脚本的属性方法
    	public Idle(BaseFSM manager)
    	{
    		this.manager=manager;
    	}
        public void OnEnter()
        {
    		//进入Idle状态脚本写在这里
        }
    
        public void OnExit()
        {
            //退出Idle状态脚本写在这里
        }
    
        public void OnUpdate()
        {
            //Idle动态的脚本写在这里
        }
    }
    
    /// <summary>
    /// Run状态
    /// </summary>
    public class Run: IState
    {
        private BaseFSM manager; 
    	//构造函数获取刚刚创建脚本的属性方法
    	public Idle(BaseFSM manager)
    	{
    		this.manager=manager;
    	}
        public void OnEnter()
        {
    		//进入Run状态脚本写在这里
        }
    
        public void OnExit()
        {
            //退出Run状态脚本写在这里
        }
    
        public void OnUpdate()
        {
            //Run状态动态的脚本写在这里
        }
    }
    

    接下来我们要返回BaseFSM脚本,去实现不同状态与其对象的管理与切换功能,基本流程如下:

    • 1,通过字典来管理状态(枚举状态)与其对象对应的行为
    • 2,实现在BaseFSM脚本中调用IState中对应三种运行状态
    • 3,实现状态的切换

    具体的代码如下:

    //在BaseFsm脚本中
    
    public class BaseFSM : MonoBehaviour
    {
     	//一个状态生命周期的三个关键函数
    	public IState currenState;
    	//定义字典通过键值对建立状态与其对象的联系
    	private Dictionary<State_Enum, IState> states = new Dictionary<State_Enum, IState>();
    	private void Awake()
        {
        	//向字典中添加对应的状态与其对象
    		states.Add(State_Enum.idle,new Idle(this);
    		states.Add(State_Enum.run,new Run(this);
    		//默认状态为idle
    		TransitionState(State_Enum.idle);
    
    	}	
    	
    	private void Update()
        {
           	//同样在Update中调用每一种状态对应的OnUpdate
            currenState.OnUpdate();
                   
        }
        
        /// <summary>
        /// 有限状态机状态切换函数
        /// </summary>
        /// <param name="type"></param>
         public void TransitionState(State_Enum type)
        {
    
            if(currenState!=null)
            {
                currenState.OnExit();
            }
            currenState = states[type];
            currenState.OnEnter();
         }
    	
    }
    

    这样一个基本的有限状态机的框架就搭建完毕了,需要通过状态切换的触发方法来进行状态的切换,比如说,当玩家按下W键时,我们可以在BaseFSM来监控这样的一个时间,从而实现状态的切换:

    //BaseFSM脚本
    
    	private void Update()
        {
           	//同样在Update中调用每一种状态对应的OnUpdate
            currenState.OnUpdate();
             
            if(Input.GetKeyDown(KeyCode.W))
            {
                TransitionState(State_Enum.run);
            }  
        }
    

    总结

    当然,目前来说这只是一个简单的有限状态机框架,如果要实现完整的功能的话,还需要一些细节去完善这个代码框架,而这样的工作就需要游戏开发者自己去完成,所以快快动手,实现自己需要的功能吧

    更多相关内容
  • https://blog.csdn.net/q764424567/article/details/119182977 下载前,请先看一下这篇文章
  • 程序员:向工具箱中添加一个强大的可视化状态机编辑器。与脚本接口或使用自定义操作扩展播放器。 :: 新的2018.3中嵌套的预置支持 :: 新的集成UI操作和事件。 :: 新的动作中的自动转换变量。 :: 新的业绩改善。 :: 新...
  • 有限状态机算是Unity开发中一个比较重要的技巧了。在游戏中,我们可能会遇到各种各样的状态,这里我以一个人物为例,我们可能要经常判断人物的生命状态或者人物的运动状态,然后做相应的操作。 简单的有限状态机....

    一:有限状态机

    有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型

    有限状态机算是Unity开发中一个比较重要的技巧了。在游戏中,我们可能会遇到各种各样的状态,这里我以一个人物为例,我们可能要经常判断人物的生命状态或者人物的运动状态,然后做相应的操作。

    简单的有限状态机可以用枚举+switch的方式实现,用Switch语句来获取状态,并且通过特定的方法来设置状态。但我们可能要在项目的很多地方的调用这段Switch方法,或者设置当前人物的状态。当状态比较多的时候,对状态的管理和获取也会变得更加麻烦。

    Switch(人物生命状态)
    {
        Case Alive:
            do something();
        Case Alive:
            do something();
        break;
    }
    
    Switch(人物运动状态)
    {
        Case Run:
            do somet
    展开全文
  • unity3D有限状态机

    2017-02-17 11:14:50
    有限状态机,附带工程及源码,清晰注释
  • unity有限状态机02

    2019-02-20 13:53:45
    视频通过一个简单的坦克射击游戏,介绍了unity游戏开发时用到的有限状态机
  • Unity有限状态机详解

    千次阅读 2016-11-04 17:34:11
    有限状态机算是Unity开发中一个比较重要的技巧了。那什么什么是有限状态机呢?在游戏中,我们可能会遇到各种各样的状态,这里我以一个人人物为例。在游戏中,我们可能要经常获取人物的生命状态或者人物的运动状态,...

    这阵子用到了有限状态机,于是花了一段时间研究了一下。在这里我会详细的讲解有限状态机的原理以及如何编写一个有限状态机。

    有限状态机算是Unity开发中一个比较重要的技巧了。那什么什么是有限状态机呢?在游戏中,我们可能会遇到各种各样的状态,这里我以一个人人物为例,我们可能要经常判断人物的生命状态或者人物的运动状态,然后做相应的操作。

    这里写图片描述

    我们可以用Switch语句来获取状态,并且通过特定的方法来设置状态。但我们可能要在项目的很多地方的调用这段Switch方法,或者设置当前人物的状态。当状态比较多的时候,对状态的管理和获取也会变得更加麻烦。

    Switch(人物生命状态)
    {
        Case Alive:
            do something();
        Case Alive:
            do something();
        break;
    }
    
    Switch(人物运动状态)
    {
        Case Run:
            do something();
        Case Idle:
            do something();
        Case Walk:
            do something();
        break;
    }
    

    所以这个时候,我们需要一个有限状态机(Finite State Machine)来集中的管理状态(State)。现在我们来看看如何设计一个有限状态机。

    有限状态机包含两个部分①状态集(FSMState),②状态管理机(FSMSystem),我们先从状态集开始设计。

    ①状态集(FSMState)的设计

    状态基代表一组状态的集合,比如上面的人物,他的状态集是这样的

    enum PersonLifeState
    {
            died,
            alive 
    }
    
    enum PersonSportState
    {
            run,
            idle,
            walk    
    }

    一个游戏当中可能需要多个状态集,所以我们在设计FSMState,最好将他设计为抽象类,这样就能通过继承FSMState,拥有一些公共的属性和方法,同时又有自己特定的状态。我设计的方式如下,通过一个List,可以让FSMState的派生类添加属于自己特有的状态,同时有一个变量保存当前的State。

    public abstract class FSMState
    {
        private List<State> list= new List<State>();
        private State curState;
    
        /*添加状态集中的状态*/
        public void AddState(State state)
        {
            if (list.Contains(state))
           {
                return;
            }
            list.Add(state);
        }
    
        /*设置当前的状态,注意这里为私有方法,这样可以让派生类无法直接设置状态,而是让状态机来统一设置*/
        private bool setCurState(State state){
            if(list.Contains(state)){
                curState=state;
                return true;
            }else{
                return false;
            }
        }
    
        ……
        //可以自己根据业务,设计一些共有的抽象方法
    }

    现在有了状态集了,我们还需要设计状态(State)。一个游戏中有各种各样的状态,我们要怎么设计呢?我们可以把特定集合的状态放在不同的枚举里,不过,我设计的是将所有状态放在一个枚举类里面。代码如下。

    public enum State
    {
        died, 
        alive,
    
        walk,
        run,
        stop 
    }`

    这样,我们就可以继承这个FSMState基类,然后添加特定的状态了。

    人物生命状态

    public class PersonLifeState :FSMState
    {
        ……
    }
    
    /*PersonLifeState 添加自己特有的状态*/
    PersonLifeState personLife= new PersonLifeState ();
    personLife.AddState(State.died);
    personLife.AddState(State.alive);
    

    人物运动状态

    public class PersonSportState :FSMState
    {
        ……
    }
    
    /*personSport 添加自己特有的状态*/
    PersonSportState personSport = new PersonSportState ();
    personSport .AddState(State.walk);
    personSport .AddState(State.run);
    personSport .AddState(State.stop );

    现在,FSMState就设计好了,我们在来看看如何设计一个FSMSystem

    ①状态管理机(FSMSystem)的设计

    一个状态管理机主要的功能有这两点

    • 能够添加和删除状态集(FSMState)
    • 能够切换和获取某个状态集(FSMState)当前的状态(State)

    知道了FSMSystem最主要的功能,我们现在就可以来自己设计一个了。我设计的FSMState代码如下

    public class FSMSystem
    {
    
        /*通过一个List专门用来存储FSMState */
        private List<FSMState> statesList=new List<>();
    
        /*添加FSMState的方法 */
        public void AddState(FSMState states)
        {
            /*做空判断检测*/
            if (statesList== null)
            {
                Debug.LogError("FSM ERROR");
            }
    
            /*当states为空时直接添加*/
            if (stateList.Count == 0)
            {
                statesList.Add(states);
                return;
            }
    
            /*当states不为空时,检查是否重复*/
            if(!statesList.contans(states)){
                states.Add(s);
            }
    
        }
    
        /*删除状态集合*/
         public void DeleteState(FSMState states)
        {
            if(!statesList.contans(states))
            {
                states.Remove(states);
            }
        }
    
        /*获取某个状态集的当前状态*/
        public State GetCurState(FSMState states)
        {   
            if(!statesList.contans(states))
            {
                states.getCurState();
            }
        }
    
        /*改变某个状态集的当前状态*/
        public void ChangeState(FSMState states,State state)
        {
            if(!statesList.contans(states))
            {
                states.setCurState();
            }
        }
    
    }
    

    这样我们就把状态机FSMSystem设计好了,我们将FSMState的派生类强行转换成FSMState基类,就能让FSMSystem统一进行管理了。上面的代码只是我设计有限状态机的一种思路,用来参考就行了。只要掌握了有限状态机的原理,你可以自己设计符合业务逻辑的状态机。虽然有限状态机比switch的方法要复杂很多,但是却能大大的简化代码逻辑。学会并使用有限状态机还是蛮重要的。

    展开全文
  • 一个简单的角色行为状态机的实现,把角色状态类当成角色类的一个属性来实现,把角色的行为拆分成多个状态子类来实现,降低代码耦合度。
  • Unity FSM有限状态机

    2020-05-22 22:36:51
    https://blog.csdn.net/a592733740/article/details/106292148
  • Unity3D日常开发】有限状态机的简单实现

    千次阅读 多人点赞 2021-07-28 16:10:58
    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875 ...Hello,大家好,我是☆恬静的小魔龙☆,正所谓学而不...如其名有限状态机,就是可以枚举出有限个状态,然后状态直接可.

    推荐阅读

    一、前言

    Hello,大家好,我是☆恬静的小魔龙☆,正所谓学而不思则罔,思而不学则殆,最近项目开发中,人物的动作特别多,用状态机去切换感觉太麻烦,然后切换的效果也并不理想。

    比如下面的状态机:
    在这里插入图片描述
    每次“走→站立→跑”,都一些卡顿,没有那么丝滑,所以就想学习一下FSM(有限状态机)。

    二、有限状态机

    什么是有限状态机:

    如其名有限状态机,就是可以枚举出有限个状态,然后状态直接可以进行切换的状态机。总体来说,有限状态机就是在不同阶段呈现出不同的运行状态的系统,这些状态是有限的、不重叠的。这样的系统在某一时刻响应其状态中的一个状态。

    为啥需要有限状态机:

    在开发中,一个角色或者AI会有很多的状态,也会产生很多的动画,比如攻击、移动、巡逻、追击、逃跑、死完,这些动画状态会不停地切换,简单的方式就是使用Switch进行判断,然后每一个case去进行相应的状态处理和转换条件判断。
    这种方式有点事简单方便,缺点就是不利于扩展,所以就出现了有限状态机去管理。
    总结来说就是,为了解决游戏过于麻烦的状态转换

    有限状态机与设计模式

    细节依赖抽象,抽象不依赖细节,基于抽象编程,让框架先跑起来。

    有限状态机参考的是状态设计模式的理念,允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类,类的行为是基于它的状态改变的。
    有限状态机,类比于Switch就是将cast中的逻辑封装到各个State对象中了,这样做可以方便扩展,后期如果需要增加新状态,只需要继承基类,添加实现就好,不用修改原来的代码,这就是开闭原则。

    源工程下载:

    https://download.csdn.net/download/q764424567/20600344

    三、有限状态机的实现

    3-1、有限状态机基类

    首先,我们需要一个基类,让其他的State对象进行继承:

    /// <summary>
    /// 状态抽象类
    /// </summary>
    public abstract class FSMState
    {
        // 所属的状态机
        protected FSMSystem m_FSM = null;
        protected FSMState(FSMSystem fsm)
        {
            m_FSM = fsm;
        }
        /// <summary>
        /// 进入状态
        /// </summary>
        public virtual void OnEnter() { }
        /// <summary>
        /// 状态中进行的动作
        /// </summary>
        public abstract void Action();
        /// <summary>
        /// 检测状态转换
        /// </summary>
        public abstract void Check();
        /// <summary>
        /// 退出状态
        /// </summary>
        public virtual void OnExit() { }
    }
    

    3-2、有限状态机系统

    接着,需要一个有限状态机系统去管理控制这些状态机,包含添加状态、删除状态、改变状态、状态改变等。

    using System.Collections.Generic;
    using UnityEngine;
    
    /// <summary>
    /// 有限状态机系统
    /// </summary>
    public class FSMSystem
    {
        /// <summary>
        /// 状态机所属游戏物体
        /// </summary>
        public GameObject OwnerGo { get; private set; }
        public Animation Ani { get; private set; }
    
        // 用字典存储每个状态ID对应的状态
        private Dictionary<StateID, FSMState> m_StateMap = new Dictionary<StateID, FSMState>();
    
        public FSMSystem(GameObject ownerGo)
        {
            OwnerGo = ownerGo;
            Ani = OwnerGo.GetComponent<Animation>();
        }
    
        /// <summary>
        /// 当前状态ID
        /// </summary>
        public StateID CurrentStateID { get; private set; }
        /// <summary>
        /// 当前状态
        /// </summary>
        public FSMState CurrentState { get; private set; }
    
        /// <summary>
        /// 添加状态
        /// </summary>
        /// <param name="id">添加的状态ID</param>
        /// <param name="state">对应的状态对象</param>
        public void AddState(StateID id, FSMState state)
        {
            // 如果当前状态为空,就设置为默认状态
            if (CurrentState == null)
            {
                CurrentStateID = id;
                CurrentState = state;
            }
            if (m_StateMap.ContainsKey(id))
            {
                Debug.LogErrorFormat("状态ID:{0}已经存在,不能重复添加!", id);
                return;
            }
            m_StateMap.Add(id, state);
        }
    
        /// <summary>
        /// 移除状态
        /// </summary>
        /// <param name="id">要移除的状态ID</param>
        public void RemoveState(StateID id)
        {
            if (!m_StateMap.ContainsKey(id))
            {
                Debug.LogWarningFormat("状态ID:{0}不存在,不需要移除", id);
                return;
            }
            m_StateMap.Remove(id);
        }
    
        /// <summary>
        /// 改变状态
        /// </summary>
        /// <param name="id">需要转换到的目标状态ID</param>
        public void ChangeState(StateID id)
        {
            if (id == CurrentStateID) return;
            if (!m_StateMap.ContainsKey(id))
            {
                Debug.LogErrorFormat("状态ID:{0}不存在!", id);
                return;
            }
            if (CurrentState != null)
                CurrentState.OnExit();
            CurrentStateID = id;
            CurrentState = m_StateMap[id];
            CurrentState.OnEnter();
        }
    
        /// <summary>
        /// 更新,在状态机持有者物体的Update中调用
        /// </summary>
        public void Update()
        {
            CurrentState.Action();
            CurrentState.Check();
        }
    }
    
    

    3-3、添加状态

    这时候,就需要看一下我们的模型有多少个动画了,比如我这个模型:
    在这里插入图片描述
    共12个动画片段,但是我只需要里面的9个动画片段,所以先定义一个枚举,将所有用到的动画片段枚举出来:

    /// <summary>
    /// 状态ID
    /// </summary>
    public enum StateID
    {
        Stand,
        Standwait,
        Walk,
        Jump1,
        Run,
        Jump2,
        Down,
        Take,
        Work
    }
    

    接着就添加状态:

    /// <summary>
    /// 站立
    /// </summary>
    public class StandState : FSMState
    {
        private float m_Timer = 0f;
        public StandState(FSMSystem fsm) : base(fsm)
        {
            Debug.Log("StandState");
        }
        public override void Action()
        {
            m_FSM.Ani.Play("Stand");
        }
        public override void Check()
        {
            m_Timer += Time.deltaTime;
            // 如果旋转达到1秒
            if (m_Timer > 0.25f)
            {
                // 转换到移动状态
                m_FSM.ChangeState(StateID.Standwait);
            }
        }
        public override void OnExit()
        {
            m_Timer = 0;
        }
    }
    /// <summary>
    /// 站立等待
    /// </summary>
    public class StandWaitState : FSMState
    {
        public StandWaitState(FSMSystem fsm) : base(fsm)
        {
            Debug.Log("StandWaitState");
        }
        public override void Action()
        {
            m_FSM.Ani.Play("Stand-wait");
        }
        public override void Check() { }
    }
    /// <summary>
    /// 走
    /// </summary>
    public class WalkState : FSMState
    {
        public WalkState(FSMSystem fsm) : base(fsm)
        {
            Debug.Log("WalkState");
        }
        public override void Action()
        {
            m_FSM.Ani.Play("walk");
        }
        public override void Check() { }
    }
    /// <summary>
    /// 小跳
    /// </summary>
    public class Jump1State : FSMState
    {
        private float m_Timer = 0f;
        public Jump1State(FSMSystem fsm) : base(fsm)
        {
            Debug.Log("Jump1State");
        }
        public override void Action()
        {
            m_FSM.Ani.Play("jump1");
        }
        public override void Check() 
        {
            m_Timer += Time.deltaTime;
            // 如果旋转达到1秒
            if (m_Timer > 0.6f)
            {
                // 转换到移动状态
                m_FSM.ChangeState(StateID.Standwait);
            }
        }
        public override void OnExit()
        {
            m_Timer = 0;
        }
    }
    /// <summary>
    /// 跑
    /// </summary>
    public class Run2State : FSMState
    {
        public Run2State(FSMSystem fsm) : base(fsm)
        {
            Debug.Log("Run2State");
        }
        public override void Action()
        {
            m_FSM.Ani.Play("run");
        }
        public override void Check() { }
    }
    /// <summary>
    /// 大跳
    /// </summary>
    public class Jump2State : FSMState
    {
        private float m_Timer = 0f;
        public Jump2State(FSMSystem fsm) : base(fsm)
        {
            Debug.Log("Jump2State");
        }
        public override void Action()
        {
            m_FSM.Ani.Play("jump2");
        }
        public override void Check()
        {
            m_Timer += Time.deltaTime;
            // 如果旋转达到1秒
            if (m_Timer > 0.75f)
            {
                // 转换到移动状态
                m_FSM.ChangeState(StateID.Standwait);
            }
        }
        public override void OnExit()
        {
            m_Timer = 0;
        }
    }
    /// <summary>
    /// 拿取
    /// </summary>
    public class TakeState : FSMState
    {
        public TakeState(FSMSystem fsm) : base(fsm)
        {
            Debug.Log("TakeState");
        }
        public override void OnEnter()
        {
            m_FSM.Ani.Play("take");
        }
        public override void Action() { }
        public override void Check() { }
        public override void OnExit() { }
    }
    /// <summary>
    /// 工作
    /// </summary>
    public class WorkState : FSMState
    {
        public WorkState(FSMSystem fsm) : base(fsm)
        {
            Debug.Log("WorkState");
        }
        public override void OnEnter()
        {
            m_FSM.Ani.Play("work");
        }
        public override void Action() { }
        public override void Check() { }
        public override void OnExit() { }
    }
    /// <summary>
    /// 蹲
    /// </summary>
    public class DownState : FSMState
    {
        public DownState(FSMSystem fsm) : base(fsm)
        {
            Debug.Log("DownState");
        }
        public override void OnEnter()
        {
            m_FSM.Ani.Play("Down");
        }
        public override void Action() { }
        public override void Check() { }
        public override void OnExit() { }
    }
    

    我为了方便,将有限状态机的基类、状态枚举、状态对象都写到一个脚本里面了,大家觉得不爽也可以分开来。

    3-4、调用动画

    新建一个Character类,用来调用动画:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Character : MonoBehaviour
    {
        // 有限状态机
        private FSMSystem m_FSM = null;
    
        private void Start()
        {
            // 实例化有限状态机
            m_FSM = new FSMSystem(this.gameObject);
            // 添加状态到有限状态机中
            m_FSM.AddState(StateID.Stand, new StandState(m_FSM));
            m_FSM.AddState(StateID.Standwait, new StandWaitState(m_FSM));
            m_FSM.AddState(StateID.Walk, new WalkState(m_FSM));
            m_FSM.AddState(StateID.Jump1, new Jump1State(m_FSM));
            m_FSM.AddState(StateID.Run, new Run2State(m_FSM));
            m_FSM.AddState(StateID.Jump2, new Jump2State(m_FSM));
            m_FSM.AddState(StateID.Down, new DownState(m_FSM));
            m_FSM.AddState(StateID.Take, new TakeState(m_FSM));
            m_FSM.AddState(StateID.Work, new WorkState(m_FSM));
        }
    
        private void Update()
        {
            // 调用有限状态机中的Update方法
            if (m_FSM != null)
                m_FSM.Update();
    
            if (Input.GetKey(KeyCode.Alpha1))
            {
                m_FSM.ChangeState(StateID.Stand);
            }
            if (Input.GetKey(KeyCode.Alpha2))
            {
                m_FSM.ChangeState(StateID.Standwait);
            }
            if (Input.GetKey(KeyCode.Alpha3))
            {
                m_FSM.ChangeState(StateID.Walk);
            }
            if (Input.GetKey(KeyCode.Alpha4))
            {
                m_FSM.ChangeState(StateID.Jump1);
            }
            if (Input.GetKey(KeyCode.Alpha5))
            {
                m_FSM.ChangeState(StateID.Run);
            }
            if (Input.GetKey(KeyCode.Alpha6))
            {
                m_FSM.ChangeState(StateID.Jump2);
            }
            if (Input.GetKey(KeyCode.Alpha7))
            {
                m_FSM.ChangeState(StateID.Down);
            }
            if (Input.GetKey(KeyCode.Alpha8))
            {
                m_FSM.ChangeState(StateID.Take);
            }
            if (Input.GetKey(KeyCode.Alpha9))
            {
                m_FSM.ChangeState(StateID.Work);
            }
        }
    }
    

    挂载到对象上:
    在这里插入图片描述
    效果图:

    在这里插入图片描述

    四、后言

    这个例子没有太多炫技的代码,作为一个学习有限状态机的入门例子来看还是很不错的。

    希望大家今天也有学习哦。
    在这里插入图片描述

    展开全文
  • Unity 可视化状态机

    2018-11-21 19:07:48
    包含状态机逻辑以及状态机可视化界面的unity package。
  • Unity3D进阶4-9】Unity3D 有限状态机

    千次阅读 2020-05-28 09:09:27
    一、目录 【Unity3D从入门到进阶】文章目录及设置这个专栏的初衷
  • Unity FSM(有限状态机)

    千次阅读 2020-04-14 01:12:47
    FSM ,有限状态机,一个可以枚举出有限个状态,并且这些状态在特定条件下是能够来回切换的。 在游戏中经常看到的一些AI,如敌人巡逻,巡逻过程中看到玩家就追击,追上了就攻击,追不上并且有了一定的距离就返回去...
  • Unity简单有限状态机实现

    千次阅读 2018-09-22 10:12:26
    【前言】 本篇来说一下关于简单有限状态机的算法实现,当然我们的几个状态会比较简单,而且本身我也是处于入门状态,所以当成一个简单的知识积累。有限状态机,顾名思义,状态是有限个的,而且状态之间是关联的,本...
  • FSM(Finite State Machine),...一个状态机就是一个设备,具有有限的状态数量,在任何给定的时间根据输入和自己预先定好的状态转换规则,从一个状态跳转到另一个状态。一个有限状态机在同一时间只能处于某一个状态。
  • unity 有限状态机使用

    千次阅读 2016-05-20 09:58:27
    有限状态机,(英语:Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。状态存储关于过去的信息,它反映从系统开始到现在时刻输入...
  • Unity有限状态机 FSM 游戏引擎:Unity 版本:2019.4.6f1 【2017版本以上均可】 编译平台:Visual Studio 2019   一、什么是FSM   FSM 全名 [Finite State Machine]。中文名 [有限状态机],又称 [有限状态...
  • 基于unity的FSM

    2018-03-23 13:24:23
    一个基于unity设计的FSM状态机代码库, 一个基于unity设计的FSM状态机代码库
  • Unity中实现有限状态机FSM

    千次阅读 2021-05-02 20:01:24
    一:什么是有限状态机? 在游戏的战斗系统开发中,角色都会有很多的状态,我们需要对这些状态进行处理以及状态之间的转换,最简单的方式是在一个Switch中进行判断,在每一个case分支中进行相应的状态处理和转换条件...
  • Unity学习笔记--FSM有限状态机的实现

    千次阅读 2022-01-05 12:01:52
    目录前言具体实现步骤一:列举出所有的状态和转换条件步骤二:创建所有状态的基类步骤三:...浅谈设计模式和其Unity中的应用:四、状态模式 具体实现 步骤一:列举出所有的状态和转换条件 /// <summary> /// 状
  • unity中实现一个有限状态机(1)

    千次阅读 2021-11-29 16:21:49
    对于每一次状态切换,都有一个从当前状态切换到另外一个状态的条件,类似于Unity动画状态机里面的箭头.对于这些条件,可以用一个枚据类型表示.添加变化条件可以在这里添加. public enum Transition { ...
  • 适用于Unity的简单有限状态机(C#) 状态机是一种管理游戏状态的非常有效的方法,可以在您的主要游戏对象(游戏结束,重新启动,继续等)或UI(buttonHover,buttonPress等)上,也可以在单个角色和NPC(AI行为,...
  • Unity有限状态机实现

    千次阅读 2015-02-14 08:26:38
    有限状态机主要是用于状态之间的切换,...那在Unity中我们如何定义有限状态机?其实有限状态机主要包括三部分,切换状态,进入状态,退出状态。接下来我们就利用Unity实现有限状态机并给大家展示如何应用。 首先我
  • Unity里实现一个有限状态机(2)

    千次阅读 2021-11-29 17:27:19
    有限状态机用来管理状态,在某一时刻只能处于一个状态 public class Fsm { //下面是当前状态的信息 private StateID currentStateId; public StateID CurrentStateId { get { return currentStateId; } } ...
  • unity3D FSM有限状态机(状态设计模式)

    万次阅读 多人点赞 2018-07-12 14:07:50
    为了解决游戏过于麻烦的状态转换(人物动画过多),使用有限状态机 缺点:代码量大 编写 使用多态和Switch new(状态设计模式) 类的介绍 PlyayCtrl:挂载在角色身上的脚本,用来控制状态机,(控制状态机...
  • Unity高级——状态机——有限状态机

    千次阅读 2016-08-30 09:34:15
    Unity高级——状态机——有限状态机
  • Unity C# 《有限状态机》的用法教程详解 有限状态机用法教程 本文提供全流程,中文翻译。 助力快速理解 FSM 有限状态机,完成游戏状态的切换 为新手节省宝贵的时间,避免采坑! 有限状态机简称: FSM —— 简称...
  • Unity3d有限状态机系统

    2017-10-31 15:38:45
    Unity3d有限状态机系统Demo源码。博客地址:blog.liujunliang.com.cn。
  • using System.Collections; using System.Collections.Generic;... //进入这个状态 public abstract void OnEnter(); //正处在这个状态 public virtual void OnStay() { } //退出这个状态 public virtual void
  • 有限状态机FSM

    2018-09-19 04:52:25
    Unity C# 《有限状态机》的用法教程详解Demo 助力快速理解 FSM 有限状态机,完成游戏状态的切换 教程地址:https://blog.csdn.net/ChinarCSDN/article/details/82263126

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,409
精华内容 7,363
关键字:

unity有限状态机