您当前的位置: 首页 >  unity

野奔在山外的猫

暂无认证

  • 4浏览

    0关注

    85博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【Unity 笔记】有限状态机 FSM

野奔在山外的猫 发布时间:2021-05-18 09:32:06 ,浏览量:4

【Unity】 有限状态机 FSM

游戏引擎:Unity 版本:2019.4.6f1 【2017版本以上均可】 编译平台:Visual Studio 2019  

一、什么是FSM

FSM 全名 [Finite State Machine]。中文名 [有限状态机],又称 [有限状态自动机],简称 [状态机]。

1.1 了解Animator组件

Unity为我们提供了Animator组件,便利开发者更加自主的实现更多动画的控制方式。 Unity Animator组件 参考:Unity Animator官方文档介绍

2.2 有限状态机的基础认识 释义举例定义有限的多个状态在不同条件下,相互转换的流程控制系统状态物体表现的行为状况行走、奔跑、自疗、射击等条件状态改变的依据受攻击、中毒、休息等状态转换表例如:中毒 - (吃药) ->健康状态机管理所有状态,协调组织状态的迁移 二、为什么选择FSM

  由于游戏内容日益的多元化、复杂化,游戏角色的行为逻辑也不断的更新更变。从最初始的行走、奔跑、跳跃,增加了受伤、治疗、拾取等诸多新的行为。亦或是调整更边以往的行走方式,增加了不同生命状态下的行为表现。或是删除了一些效果欠佳的行为表现。致使了开发人员在复杂的动画状态机面前出现更新修改工作量增大。   FSM 有限状态机,意在独立状态与条件之间的联系,使其之间互不影响,便利开发人员在应对此类问题,减少工作量,以及后期行为扩展、修改等开发中的便利化。

三、FSM的实现 3.0 二类一基类 二类 一基类解释FSM BaseFSM State代表 具体[状态],隔离状态机与状态的变化FSM Trigger代表 具体[条件],隔离状态机与条件的变化 3.1 状态类 FSMState

FSMState类主要完成以下工作

  • 存储条件的列表
  • 存储条件与状态之间的映射关系
  • 实现传入条件,返回指定状态的逻辑方法
  • 状态的进入,进行时,退出的抽象方法【服务于子类】
3.1.1 代码块
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace FSM
{
    public class FsmState
    {   
        private List triggerList;  //条件列表     
        private Dictionary map;   //策划配置的映射表(条件 --> 状态)

        [HideInInspector] public T Fsm;

        public FsmState()
        {
            triggerList = new List();
            map = new Dictionary();
        }

        /// 
        /// 添加映射
        /// 
        /// 
        /// 
        public void AddMap(string triggerName,string stateName)
        {
            map.Add(triggerName, stateName);

            Type type = Type.GetType("AI.FSM." + triggerName + "Trigger");
            FsmTrigger trigger = Activator.CreateInstance(type) as FsmTrigger;
            //为条件提供状态机引用
            trigger.Fsm = Fsm;
            triggerList.Add(trigger);
        }

        /// 
        /// 检查条件:遍历条件,判断谁满足逻辑
        /// 
        /// 
        public string Check()
        {
            for (int i = 0; i  e.GetType().Name == stateName+"State");
            
            currentState.OnStateEnter();  //进入当前状态
        }
    }
}
3.3.2 关于InitDefaultState( )的说明

InitDefaultState():初始化默认状态。

private void InitDefaultState()
{
    //在状态列表中查找默认状态
    defaultState = stateList.Find(e => e.GetType().Name == defaultStateName + "State");
    currentState = defaultState;
    currentState.OnStateEnter();
}

  我们在开头public string defaultStateName;声明了一个尚未填写的defaultStateName,它可以是站立idle,也可以是跳跃jump等。需要的是传入一个动画命名。使得我们以更灵活的设置默认动画状态。其中一行:

defaultState = stateList.Find(e => e.GetType().Name == defaultStateName + "State");
  • 从状态列表中查找所需求的默认状态,我们使用这行代码是为了避免在状态列表获取动画信息前,我们查找不到对应的动画状态。即使确实存在,但我们的查找先于状态列表添加动画状态。在确认找到指定动画后,进入对应的动画状态。
补充:FSMConfigReader FSM状态机配置获取

(致谢:水管工人玛丽奥 的 纠正提醒)

public class FSMConfigReader
{
    //外层字典:key 状态名称   value 字典
    //内层字典:key 条件名称   value 状态名称
    public Dictionary map;
    private string mainKey;

    public FSMConfigReader(string fileName)
    {
        map = new Dictionary();
        string content = ConfigurationReader.GetConfigFile(fileName);
        ConfigurationReader.ReadConfigFile(content, LineHandler);
    }

    private void LineHandler(string line)
    {
        line = line.Trim(); //剔除字符串空格
        if (line == "") return;
        if (line.StartsWith("["))
        {
            //如果该行以[开始,表示状态  [Idle]
            mainKey = line.Substring(1, line.Length - 2);
            map.Add(mainKey, new Dictionary());
        }
        else
        {
            //表示条件  NoHealth>Dead
            string[] keyValue = line.Split('>');
            map[mainKey].Add(keyValue[0], keyValue[1]);
        } 
    }
}

LineHandler():笔者印象中是对命名文字的处理,指某一状态到另一状态的过程 例如一些动作的变化: Health -> Hurt 这一过程通过字符分割得到状态的映射进行注册。 譬如:获取 [Idle] 那么以此的映射有 idle -> run / idle -> walk 等

关注
打赏
1659777066
查看更多评论
立即登录/注册

微信扫码登录

0.0423s