您的位置:首页 > 移动开发 > Unity3D

Unity 有限状态机FSM原理剖析

2018-02-28 09:53 609 查看
本文分析的是wiki上有限状态机给出的代码:链接地址
下面是删除注释精简后的代码:using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum Transition
{
    /*输入切换状态触发量,如OnFirstButtonClick=0,
                            OnSecondButtonClick=1,
                            ……
    */
}
public enum StateID
{
    /*输入状态ID,如ShowFirstPanelID=0,
                    ShowSecondPanelID=1,
                    ……
    */
}

public abstract class FSMState
{
    protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();
    protected StateID stateID;
    public StateID ID { get { return stateID; } }

    //关联切换状态触发量与要切换到的状态ID
    public void AddTransition(Transition trans, StateID id)
    {
        if (map.ContainsKey(trans))
        {
            return;
        }

        map.Add(trans, id);
    }

    public void DeleteTransition(Transition trans)
    {
        if (map.ContainsKey(trans))
        {
            map.Remove(trans);
            return;
        }
    }

    public StateID GetOutputState(Transition trans)
    {
        if (map.ContainsKey(trans))
        {
            return map[trans];
        }
        return 0;//若查询不到对应的id,将返回StateID的第一个枚举量
    }

    public virtual void DoBeforeEntering() { }
    public virtual void DoBeforeLeaving() { }

    public abstract void Reason(GameObject player, GameObject npc);
    public abstract void Act(GameObject player, GameObject npc);



//FSMSystem-------------------------------------------------
public class FSMSystem
{
    private List<FSMState> states;

    private StateID currentStateID;
    public StateID CurrentStateID { get { return currentStateID; } }
    private FSMState currentState;
    public FSMState CurrentState { get { return currentState; } }

    public FSMSystem()
    {
        states = new List<FSMState>();
    }

    public void AddState(FSMState s)
    {
        //默认是将第一个传入的state设置为当前状态
        if (states.Count == 0)
        {
            states.Add(s);
            currentState = s;
            currentStateID = s.ID;
            return;
        }

        fore
4000
ach (FSMState state in states)
        {
            if (state.ID == s.ID)
            {
                return;
            }
        }
        states.Add(s);
    }

    public void DeleteState(StateID id)
    {
        foreach (FSMState state in states)
        {
            if (state.ID == id)
            {
                states.Remove(state);
                return;
            }
        }
    }

    public void PerformTransition(Transition trans)
    {
        StateID id = currentState.GetOutputState(trans);
        // Update the currentStateID and currentState
        currentStateID = id;
        foreach (FSMState state in states)
        {
            if (state.ID == currentStateID)
            {
                currentState.DoBeforeLeaving();
                currentState = state;
                currentState.DoBeforeEntering();
                break;
            }
        }

    } 

使用方法:直接在Unity下创建FSMSystem.cs,将代码全部复制过去即可。
代码中包含两个类:FSMSystem、抽象类FSMState。   其中FSMState底下分了几个state继承类,每个类都有各自的ID号。当执行FSMSystem下的PerformTransition函数时,需要传入与切换到下一状态事件相关的枚举触发量,FSMSystem会根据此枚举量找到切换到对应事件的id,接着遍历所有FSMState继承类的id,寻找相符合的,然后执行当前事件的Leaving方法,与执行下一事件的Enting方法,并将当前事件=下一事件。
代码实现效果:调用FSMSystem中PerformTransition函数,告诉它要切换到什么状态,FSMSystem即会执行当前状态的Leving方法与下一状态的Entering方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: