FSM狀態機及C#反射實現邏輯

被迫吃冰淇淋的小学生發表於2024-03-16

零、大致邏輯

1.初始化 Start

元件->狀態->狀態內部初始化->進入初始狀態

2.執行時 Update

遍歷狀態的所有條件->

不滿足所有條件物件->執行當前狀態執行時邏輯->進行一次玩家搜尋

滿足某一個條件物件->執行當前狀態退出邏輯->執行狀態改變->執行新狀態進入邏輯->執行新狀態執行時邏輯->進行一次玩家搜尋

3.銷燬時 OnDestroy

清空所有狀態內部資料->清空狀態機資料->清空所有狀態

一、狀態機配置檔案和它的工廠

狀態機需要知道當前物件會有哪些狀態,且狀態需要知道有哪些條件

並以Dictionary<狀態, Dictionary<條件, 目標狀態>>存到狀態機內部

狀態機填一個檔名,資料以txt方式存在於StreamAsset資料夾下

FSM狀態機及C#反射實現邏輯

使用反射,將這一個個字串變成狀態類和條件類

那麼,該如何去拿到這些字串呢

我們使用一個工廠,狀態機傳字串給工廠

工廠看看自己的快取中有沒有,有就給你,沒有就new

下方的類就和一個字串相匹配Dictionary<string, FSMConfigFlie>

狀態機配置檔案初始化

public class FSMConfigFlie
{
    public Dictionary<string, Dictionary<string, string>> Map;
    private string current = "";
    
    //這是供工廠使用的檔案讀取方法
    public FSMConfigFlie(string fileName)
    {
        Map = new Dictionary<string, Dictionary<string, string>>();
        BuildMap(ConfigFile.GetConfigFile(fileName), MyBuildMap);
    }
    
    //這是其他地方寫的享元函式,但由於篇幅太大,就直接提過來了
    private void BuildMap(string paths,Action<string> handler)
    {
        using (StringReader reader = new StringReader(paths))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                handler(line);
            }
        }
        //StringReader是個資料流,在使用完畢後要關閉,倘若中途出錯,就不會關了
        //但是用using括起來,那麼只要它執行完畢, 肯定關了。
    }

    //詳細解析
    private void MyBuildMap(string line)
    {
        if (line.StartsWith("["))
        {
            current = line.Substring(1, line.Length - 2);
            Map.Add(current, new Dictionary<string, string>());
        }
        else if (line.Contains(">"))
        {
            string[] keyValue = line.Split('>');
            Map[current].Add(keyValue[0], keyValue[1]);
        }
    }
}
配置檔案Map快取
 public class FSMConfigFlieFactory
{
    //快取
    public static Dictionary<string, FSMConfigFlie> OMap;
    
    //靜態變數
    static FSMConfigFlieFactory()
    {
        OMap = new Dictionary<string, FSMConfigFlie>();
    }
    
    //供外部使用的狀態資料獲取方法
    public static Dictionary<string, Dictionary<string, string>> GetMap(string file)
    {
        if (!OMap.ContainsKey(file))
        {
            OMap.Add(file, new FSMConfigFlie(file));
        }
        return OMap[file].Map;
    }
}

此時,我們就獲得了

Dictionary<狀態, Dictionary<條件, 目標狀態>>

二、狀態抽象類

然後,就是狀態類,拿到Dictionary<狀態, Dictionary<條件, 目標狀態>>中的Value

三、條件抽象類

四、FSMBase程式碼

相關文章