游戏引擎:Unity 版本:2019.4.6f1 【2017版本以上均可】 编译平台:Visual Studio 2019
一、什么是FSMFSM 全名 [Finite State Machine]。中文名 [有限状态机],又称 [有限状态自动机],简称 [状态机]。
1.1 了解Animator组件Unity为我们提供了Animator组件,便利开发者更加自主的实现更多动画的控制方式。 参考:Unity Animator官方文档介绍
由于游戏内容日益的多元化、复杂化,游戏角色的行为逻辑也不断的更新更变。从最初始的行走、奔跑、跳跃,增加了受伤、治疗、拾取等诸多新的行为。亦或是调整更边以往的行走方式,增加了不同生命状态下的行为表现。或是删除了一些效果欠佳的行为表现。致使了开发人员在复杂的动画状态机面前出现更新修改工作量增大。 FSM 有限状态机,意在独立状态与条件之间的联系,使其之间互不影响,便利开发人员在应对此类问题,减少工作量,以及后期行为扩展、修改等开发中的便利化。
三、FSM的实现 3.0 二类一基类 二类 一基类解释FSM BaseFSM State代表 具体[状态],隔离状态机与状态的变化FSM Trigger代表 具体[条件],隔离状态机与条件的变化 3.1 状态类 FSMStateFSMState类主要完成以下工作
- 存储条件的列表
- 存储条件与状态之间的映射关系
- 实现传入条件,返回指定状态的逻辑方法
- 状态的进入,进行时,退出的抽象方法【服务于子类】
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");
- 从状态列表中查找所需求的默认状态,我们使用这行代码是为了避免在状态列表获取动画信息前,我们查找不到对应的动画状态。即使确实存在,但我们的查找先于状态列表添加动画状态。在确认找到指定动画后,进入对应的动画状态。
(致谢:水管工人玛丽奥 的 纠正提醒)
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 等