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

23 篇文章 0 订阅
4 篇文章 0 订阅
  • 有限状态机的基类,包含各种状态
  • 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);
            }
        }
    }
    
  •  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值