zoukankan      html  css  js  c++  java
  • 有限状态机(FSM)

    在游戏开发中,AI是个永恒不变的话题,如果你要的AI只是很简单的一个逻辑
    那么有限状态机是一个很好的解决方案,尽管在实际开发中,AI的设计并不是一个简单的逻辑,
    如果用有限状态机,维护起来会非常麻烦,但还是有必要记一笔。

    为什么说维护起来很麻烦?
    画一个图就知道了。
    在状态不是很多的时候,要维护的状态就少,实现起来也很简单。

    但是,一旦状态一多,要维护的状态就多了,
    每增加一个状态,就要维护这个状态到其他各个状态之间的实现
    当状态越来越多的时候,你就会觉得心有余而力不足了。

    代码1:

    using System;
    using System.Collections;
    using System.Collections.Generic;
     
    namespace ShiHuanJue.FSM
    {
        public abstract class FSMParent
        {
            #region 公共变量
     
            public string m_currentState = string.Empty;
     
            #endregion
     
            #region 私有变量
     
            protected Dictionary<string, IState> theFSM = new Dictionary<string, IState>();
     
            #endregion
     
            public FSMParent()
            {
            }
     
            public virtual void ChangeStatus(string newState, params Object[] args)
            {
                if (this.m_currentState == newState)
                {
                    UnityEngine.Debug.Log("oldState = newState");
                    return;
                }
     
                if (!this.theFSM.ContainsKey(newState))
                {
                    UnityEngine.Debug.Log("newState is not in stateList");
                    return;
                }
     
                if(this.theFSM.ContainsKey(this.m_currentState))
                    this.theFSM[this.m_currentState].Exit(args);
                this.theFSM[newState].Enter(args);
                this.m_currentState = newState;//更改当前状态
                this.theFSM[newState].Process(args);
            }
        }
    }

    代码2:

    using System;
    namespace ShiHuanJue.FSM
    {
        public interface IState
        {
            // 进入该状态
            void Enter(params Object[] args);
     
            // 离开状态
            void Exit(params Object[] args);
     
            // 状态处理
            void Process(params Object[] args);
        }
    }

    代码3:

    namespace ShiHuanJue.FSM
    {
        // 状态
        static public class MotionState
        {
            static readonly public string IDLE = "idle";
            static readonly public string WALKING = "walking";
            static readonly public string DEAD = "dead";
            static readonly public string ATTACKING = "attacking";
        }
    }

    代码就上面3个,很简单吧。
    怎么用呢?

    using System;
    using System.Collections;
     
    namespace ShiHuanJue.FSM
    {
        static public class  RoleStateSet 
        {
            static public RoleIdle stateIdle = new RoleIdle();
            static public RoleWalking stateWalking = new RoleWalking();
            static public RoleDead stateDead = new RoleDead();
            static public RoleAttacking stateAttackint = new RoleAttacking();
        }
     
        public class FSMRole : FSMParent
        {
            public FSMRole()
            {
                theFSM.Add(MotionState.IDLE, RoleStateSet.stateIdle);
                theFSM.Add(MotionState.WALKING, RoleStateSet.stateWalking);
                theFSM.Add(MotionState.DEAD, RoleStateSet.stateDead);
                theFSM.Add(MotionState.ATTACKING, RoleStateSet.stateAttackint);
            }
     
            public override void ChangeStatus(string newState, params Object[] args)
            {
                base.ChangeStatus(newState,args);
            }
        }
    }

    实现各个状态的逻辑。这里就贴一个Idle的。其它状态格式都一样,只是实现不一样。

    using UnityEngine;
    using System.Collections;
     
    namespace ShiHuanJue.FSM
    {
        public class RoleIdle : IState
        {
            public void Enter(params System.Object[] args)
            {
                Debug.Log("RoleIdle Enter");
            }
     
            public void Exit(params System.Object[] args)
            {
                Debug.Log("RoleIdle Exit");
            }
     
            public void Process(params System.Object[] args)
            {
                Debug.Log("RoleIdle Process");
            }
        }
    }

    测试一下咯:

    using UnityEngine;
    using System.Collections;
    using ShiHuanJue.FSM;
     
    public class Test : MonoBehaviour
    {
        void Start()
        {
            FSMRole roleAI = new FSMRole();
            Debug.Log(roleAI.m_currentState);
     
            roleAI.ChangeStatus(MotionState.IDLE);
            Debug.Log(roleAI.m_currentState);
     
            roleAI.ChangeStatus(MotionState.WALKING);
            Debug.Log(roleAI.m_currentState);
     
            roleAI.ChangeStatus(MotionState.IDLE);
            Debug.Log(roleAI.m_currentState);
        }
    }

    代码都在这了,实际用的也不多,工程就不上传了。用的不多,只是在这记一笔。
    实际开发中,还是推荐用行为树。
    行为树下次再说,我会先自己写一个行为树之后,分析下缺点,然后介绍一下腾讯开源的行为树框架。
    我觉得学习,再理解了它的原理之后,就可以拿现有完善的框架来用,站在巨人的肩膀上,你才可以看的更远,知道自己是多么的渺小。
    敬请期待~!

  • 相关阅读:
    【Vijos-P1285】佳佳的魔法药水-Dijkstra思想
    【NOIP2009提高组T3】最优贸易-双向SPFA
    【NOIP2009提高组T3】最优贸易-双向SPFA
    【Vijos-P1046】观光旅游-Floyd求最小环
    【Vijos-P1046】观光旅游-Floyd求最小环
    【Vijos-P1060】盒子-DP+组合数学
    mysql 结合keepalived测试
    set global read_only=0; 关闭只读,可以读写 set global read_only=1; 开始只读模式
    set global read_only=0; 关闭只读,可以读写 set global read_only=1; 开始只读模式
    -F, --flush-logs
  • 原文地址:https://www.cnblogs.com/joeshifu/p/5488818.html
Copyright © 2011-2022 走看看