人工智能02_有限状态机

有限状态机基类(状态的条件,ID,条件ID的字典,增加删除条件,根据条件获取ID,虚方法进入状态,虚方法离开状态,抽象方法状态下的行为,抽象方法状态的触发条件)

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

    protected FSMManager fsmMng;
    public FSMState(FSMManager fsmM)
    {
        fsmMng = fsmM;
    }

    protected StateID stateId;

    public StateID Id { get { return stateId; } }
    //条件和状态id的映射
    protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();

    public void AddTransition(Transition ts, StateID id)
    {
        if (ts == Transition.NullTransition || id == StateID.NullStateId || map.ContainsKey(ts))
        {
            Debug.LogError("出错");
            return;
        }
        map.Add(ts, id);
    }
    public void DeleteTransition(Transition ts)
    {
        if (ts == Transition.NullTransition || map.ContainsKey(ts))
        {
            Debug.LogError("出错");
            return;
        }
        map.Remove(ts);
    }

    public StateID GetOutputState(Transition trans)
    {
        if (map.ContainsKey(trans))
        {
            return map[trans];
        }
        return StateID.NullStateId;
    }
    public virtual void DoBeforeEnter() { }
    public virtual void DoAfterLeaving() { }
    public abstract void Act(GameObject npc);
    //判断转换条件
    public abstract void Reason(GameObject npc);
}

状态管理类:当前状态,状态ID状态字典,管理中增加状态,管理中删除状态,改变状态,更新状态

public class FSMManager 
{
    private StateID currentId;
    private FSMState currentState;
    private Dictionary<StateID, FSMState> StatesDic = new Dictionary<StateID, FSMState>();

    public void AddState(FSMState s)
    {
        if (s == null)
        {
            Debug.LogError("FSMState不能为空");
            return;
        }
        if (currentState == null)
        {
            currentId = s.Id;
            currentState = s;
        }
        if (StatesDic.ContainsKey(s.Id))
        {
            Debug.LogError("状态" + s.Id + "已经存在,无法重复添加");
            return;
        }
        StatesDic.Add(s.Id, s);
    }

    public void DeleteState(StateID id)
    {
        if (id == StateID.NullStateId)
        {
            Debug.LogError("无法删除空状态"); return;
        }
        if (StatesDic.ContainsKey(id))
        {
            StatesDic.Remove(id);
        }
        else
        {
            Debug.LogError("状态不存在");
        }
    }

    public void ChangeState(Transition tst)
    {
        if (tst == Transition.NullTransition)
        {
            Debug.LogError("空条件无法转换");
            return;
        }
        StateID id = currentState.GetOutputState(tst);
        if (id == StateID.NullStateId)
        {
            Debug.LogWarning(currentId + "根据条件" + tst + "无法转换"); return;
        }
        if (StatesDic.ContainsKey(id))
        {
            FSMState state = StatesDic[id];
            currentState.DoAfterLeaving();
            currentId = id;
            currentState = state;
            currentState.DoBeforeEnter();
        }
        else
        {
            Debug.LogError("条件出错" + tst);
        }
    }

    //更新状态
    public void Update(GameObject npc) 
    {
        currentState.Act(npc);
        currentState.Reason(npc);
    }
}

巡逻状态:继承自基类,构造函数(当前id,玩家,巡逻范围),重写抽象类当前状态下的行为,重写抽象类触发当前状态的条件

public class PatrolState:FSMState
{
    private Transform PlayerTranform;
    public List<Transform> path = new List<Transform>();
    public int index = 0;
    public PatrolState(FSMManager fsm)
        : base(fsm)
    {
        stateId = StateID.Patrol;
        Transform pathGo = GameObject.Find("Path").transform;
        PlayerTranform = GameObject.Find("Player").transform;
        Transform[] childrens = pathGo.GetComponentsInChildren<Transform>();
        foreach (Transform child in childrens)
        {
            if (child != pathGo)
            {
                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(PlayerTranform.position, npc.transform.position) < 3)
        {
            fsmMng.ChangeState(Transition.SeePlayer);
        }
    }
}

追踪状态:继承基类,构造函数(当前id,玩家),继承抽象类的表现,继承抽象类的触发条件,

public class ChaseState : FSMState {

    private Transform PlayerTranform;
    public ChaseState(FSMManager fsm)
        : base(fsm)
    {
        stateId = StateID.Chase;
        PlayerTranform = GameObject.Find("Player").transform;
    }
    public override void Act(GameObject npc)
    {
        npc.transform.LookAt(PlayerTranform.position);
        npc.transform.Translate(Vector3.forward * 2 * Time.deltaTime);
    }

    public override void Reason(GameObject npc)
    {
        if (Vector3.Distance(PlayerTranform.position, npc.transform.position) > 6)
        {
            fsmMng.ChangeState(Transition.LostPlayer);
        }
    }
}

敌人:初始化的时候把巡逻状态,追踪状态添加到管理类中,每帧更新管理类的Update(行为和转化条件)

public class Enemy : MonoBehaviour {

    public FSMManager fsm;
	// Use this for initialization
	void Start () {
        InitFSM();
	}
	
	// Update is called once per frame 
	void Update () {
        fsm.Update(this.gameObject);
	}
    void InitFSM()
    {
        fsm = new FSMManager();
        FSMState patrolState = new PatrolState(fsm);
        
        FSMState ChaseState = new PatrolState(fsm);
        patrolState.AddTransition(Transition.SeePlayer, StateID.Chase);
        patrolState.AddTransition(Transition.LostPlayer, StateID.Patrol);
        fsm.AddState(patrolState);
        fsm.AddState(ChaseState);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_35647121/article/details/93377125