AI-有限状态机(追击,巡逻)

本文详细介绍了一种游戏AI设计模式——有限状态机(FSM)的实现过程。通过定义状态、过渡条件和行为,实现了敌人AI从巡逻到追逐玩家的状态转换。代码示例展示了如何在Unity中使用C#构建FSM,包括状态枚举、状态类和状态系统。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 有限状态机的基类,包含各种状态
  • 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; } }
        protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();
        protected FSMSystem fsm;
    
        public FSMState(FSMSystem fsm)
        {
            this.fsm = fsm;
        }
    
        public void AddTransition(Transition transition,StateID id)
        {
            if (transition==Transition.NullTransition)
            {
                Debug.LogError("不允许NullTransition");return;
            }
            if (id==StateID.NullStateID)
            {
                Debug.LogError("不允许NullStateID");return;
            }
            if (map.ContainsKey(transition))                // 判断key是否存在
            {
                Debug.LogError("添加转换条件的时候" + transition + "已经存在于map中");return;
            }
            map.Add(transition, id);
        }
    
        public void DeleteTransition(Transition transition)
        {
            if (transition == Transition.NullTransition)
            {
                Debug.LogError("不允许NullTransition"); return;
            }
            if (map.ContainsKey(transition)==false)                // 判断key是否存在
            {
                Debug.LogError("删除转换条件的时候" + transition + "不存在于map中"); return;
            }
            map.Remove(transition);
        }
    
        public StateID GetOutputState (Transition transition)
        {
            if (map.ContainsKey(transition))
            {
                return map[transition];
            }
            return StateID.NullStateID;
        }
    
        //进入状态之前的虚函数
        public virtual void DoBeforEntering() { }
        //离开状态,状态发生转换
        public virtual void DoAfterLeaving() { }
        //抽象方法必须重写
        public abstract void Act(GameObject gameObject);
        //判断转换条件
        public abstract void Reason(GameObject gameObject);
    }
    
  • 控制状态之间的转换
  • 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("FSMState不能为空");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 DeleteState(StateID id)
        {
            if (id==StateID.NullStateID)
            {
                Debug.LogError("无法删除空状态");return;
            }
            if (states.ContainsKey(id)==false)
            {
                Debug.LogError("无法删除不存在的:" + id);return;
            }
            states.Remove(id);
        }
    
        //根据条件进行状态切换
        public void PerformTransition(Transition transition)
        {
            if (transition ==Transition.NullTransition)
            {
                Debug.LogError("无法执行空的转换条件");return;
            }
            StateID id = currentState.GetOutputState(transition);
    
            if (id==StateID.NullStateID)
            {
                Debug.LogWarning("当前状态" + currentStateID + "无法根据转换条件" + transition + "发生转换");return;
            }
            FSMState fSMState = states[id];
    
            currentState.DoAfterLeaving();          //旧状态离开
            currentState = fSMState;
            currentStateID = id;
            currentState.DoBeforEntering();         //新状态进入
        }
    
        //调用Act方法
        public void Update(GameObject gameObject)
        {
            currentState.Act(gameObject);
            currentState.Reason(gameObject);
        }
    
    }
    
  • 敌人类
  • using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Enemy : MonoBehaviour {
    
        private FSMSystem fsm;
    	
    	void Start () {
            InitFSM();
    	}
    	
    	//对有限状态机进行初始化
        private void InitFSM()
        {
            fsm = new FSMSystem();
            FSMState patrolState = new PatrolState(fsm);
            //转换条件
            patrolState.AddTransition(Transition.SeePlayer,StateID.Chase);
    
            FSMState chaseState = new ChaseState(fsm);
            chaseState.AddTransition(Transition.LostPlayer, StateID.Patrol);
    
            fsm.AddState(patrolState);
            fsm.AddState(chaseState);
        }
    
    	void Update () {
            fsm.Update(this.gameObject);
    	}
    }
    
  • 巡逻状态和追击状态
  • using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class PatrolState : FSMState
    {
        //路径点
        private List<Transform> path = new List<Transform>();
        private int index = 0;      //移动的开始索引
        private Transform playerTransform;
    
        public PatrolState(FSMSystem fsm) : base(fsm)
        {
            stateID = StateID.Patrol;
    
            //在这里获取一次,节省性能
            Transform pathTran = GameObject.Find("Path").transform;
            Transform[] children = pathTran.GetComponentsInChildren<Transform>();   //还包含父物体
            //剔除父物体
            foreach (Transform child in children)
            {
                if (child!= pathTran)
                {
                    path.Add(child);
                }
            }
    
            playerTransform = GameObject.Find("Player").transform;
    
        }
    
        //这个方法在FSMSystem中调用
        public override void Act(GameObject gameObject)
        {
            gameObject.transform.LookAt(path[index].position);
            gameObject.transform.Translate(Vector3.forward * Time.deltaTime * 3);
            if (Vector3.Distance(gameObject.transform.position,path[index].position)<1)     //自身位置与目标位置的距离
            {
                index++;
                index %= path.Count;    //index在数组内循环
            }
        }
    
        public override void Reason(GameObject gameObject)
        {
            //与主角距离小于3的时候开始追击玩家
            if (Vector3.Distance(playerTransform.position,gameObject.transform.position)<3)
            {
                fsm.PerformTransition(Transition.SeePlayer);
            } 
        }
    }
    
  • using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class ChaseState : FSMState
    {
        private Transform playerTransform;
    
        public ChaseState(FSMSystem fsm) : base(fsm)
        {
            stateID = StateID.Chase;
            playerTransform = GameObject.Find("Player").transform;
        }
    
        public override void Act(GameObject gameObject)
        {
            gameObject.transform.LookAt(playerTransform.position);
            gameObject.transform.Translate(Vector3.forward * 2 * Time.deltaTime);
        }
    
        public override void Reason(GameObject gameObject)
        {
            //与主角距离大于6时,执行寻路状态
            if (Vector3.Distance(playerTransform.position, gameObject.transform.position) > 6)
            {
                fsm.PerformTransition(Transition.LostPlayer);
            }
        }
    }
    
  •  
<think>嗯,用户想了解有限状态机在计算机科学中的应用,特别是在软件开发和算法设计中的场景。首先,我需要回忆有限状态机的基本概念,然后找出它在不同领域的具体应用例子。记得有限状态机(FSM)是由状态、事件和转换组成的模型,用来描述系统在不同状态间的转换。用户提到的应用场景可能包括软件设计中的状态管理,比如用户界面或者游戏AI的状态切换。比如,引用[2]提到嵌入式C编程中的状态机模式,可能和硬件控制或协议处理有关。另外,引用[3]中的状态模式用于对象行为随状态改变的情况,比如订单状态的变化。算法设计方面,FSM可以用于字符串匹配,比如正则表达式的实现,或者词法分析中的token识别。例如,KMP算法中的状态转移可能和FSM有关。另外,网络协议中的状态管理,如TCP连接的状态转换,也是FSM的应用。还需要考虑用户可能的背景,可能是开发者或学生,想了解如何实际应用FSM。可能需要给出具体的例子,比如自动售货机、电梯控制,或者解析器中的使用。同时,结合引用中的内容,如引用[1]提到状态机的学习和实践,可以建议用户通过项目来加深理解。 要注意用户可能分不清状态机和其他设计模式的区别,比如策略模式,引用[2]提到策略和状态机在简单应用中可能相似,但实际应用场景不同。所以需要明确FSM的特点,比如状态转换的明确性和事件驱动。 总结回答结构:先定义FSM,然后分软件开发和算法设计两部分,列举具体场景,每个场景举例说明,并引用相关文献。最后生成相关问题,帮助用户深入探索。</think>### 有限状态机(FSM)在计算机科学中的应用 有限状态机(Finite State Machine, FSM)是一种描述系统行为的形式化模型,通过**有限状态**、**事件触发**和**状态转移规则**实现逻辑控制。以下是其在软件开发和算法设计中的典型应用场景: --- #### 一、软件开发中的应用 1. **用户界面交互** - 例如,登录流程的状态转换:初始态 → 输入用户名 → 输入密码 → 验证 → 成功/失败[^3]。 - 使用状态机可避免代码冗余,例如通过`switch-case`或状态模式(State Pattern)实现[^3]。 2. **协议解析** - 网络通信协议(如TCP)的状态管理:连接建立(SYN)、数据传输(ESTABLISHED)、断开连接(FIN)[^2]。 - 嵌入式系统中串口通信的帧解析(起始位、数据位、校验位)[^2]。 3. **游戏开发** - NPC行为逻辑:巡逻追击 → 攻击 → 返回初始位置,每个状态对应不同的行为函数[^1]。 4. **工作流引擎** - 订单处理系统:待支付 → 已支付 → 发货中 → 已完成/取消,状态转移由外部事件(支付、超时)触发[^3]。 --- #### 二、算法设计中的应用 1. **字符串匹配与正则表达式** - 正则表达式引擎的核心是状态机,例如匹配`a*b`时,状态从“初始”转移到“匹配a”再到“匹配b”[^1]。 - KMP算法中的部分匹配表(Partial Match Table)本质上是预生成的状态转移表。 2. **词法分析(Lexical Analysis)** - 编译器将源代码拆分为token(标识符、运算符等),例如通过状态机识别`if`、`while`等关键字[^2]。 3. **控制流验证** - 检测代码中的非法跳转(如未初始化的变量使用),通过状态机跟踪变量生命周期[^1]。 --- #### 三、与其他设计模式的对比 - **策略模式**:关注**同一问题不同解法**的动态切换,例如排序算法的运行时选择[^3]。 - **状态模式**:强调**对象内部状态变化导致行为改变**,例如电梯门的开启/关闭状态[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值