欢迎加入光光的奇妙冒险,我是你们的煎饼光子老师。
这期我们来速通一套有限状态机框架
我认为一个有限状态机必须要满足这三个条件
如果结合代码说就是
1.枚举表示的状态类型
2.当前处于的状态
3.通过Switch等逻辑去切换状态
首先我们创建一个FSM,也就是我们的有限状态框架
在代码中我已经给出了详细的注释
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//状态类型用枚举表示
public enum E_StateType
{
Idle,Walk
}
//状态接口
public interface IState
{
void OnEnter();
void OnUpdate();
void OnExit();
// void OnFixedUpdate();
// void OnCheck();
}
[System.Serializable]
public class Blackboard
{
//此处存储共享数据,或向外展示的数据,可配置的数据
}
public class FSM
{
public IState currentState;//当前状态
public Dictionary<E_StateType, IState> stateDic;//状态字典
public Blackboard blackboard;//共享信息的黑板
public FSM(Blackboard blackboard)
{
stateDic = new ();
this.blackboard = blackboard;
}
/// <summary>
/// 切换状态
/// </summary>
/// <param name="stateType"></param>
public void SwitchState(E_StateType stateType)
{
if(!stateDic.ContainsKey(stateType))
{
return;
}
else
{
//如果当前状态不为空,则调用OnExit
if(currentState!=null)
currentState.OnExit();
currentState=stateDic[stateType];
currentState.OnEnter();
}
}
/// <summary>
/// 添加状态
/// </summary>
/// <param name="stateType"></param>
/// <param name="state"></param>
public void AddState(E_StateType stateType, IState state)
{
if(!stateDic.ContainsKey(stateType))
{
stateDic.Add(stateType, state);
}
}
public void OnUpdate()
{
currentState.OnUpdate();
}
// public void OnFixedUpdate()
// {
// currentState.OnFixedUpdate();
// }
// public void OnCheck()
// {
// currentState.OnCheck();
// }
}
接着我们来实际使用一下这个有限状态机框架
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//为某个对象专门创建一个黑板
[System.Serializable]
public class MyBlackboard:Blackboard
{
public Animator anim;
public Transform transform;//在外面关联某个对象的Transform
public Vector2 targetPos;
public float idleTime;
public float moveSpeed;
}
public class IdleState : IState
{
private float idleTimer;
private FSM fsm;
private MyBlackboard blackboard;
//构造函数
public IdleState(FSM fSM)
{
this.fsm = fSM;
this.blackboard = fSM.blackboard as MyBlackboard;
}
public void OnEnter()
{
idleTimer = 0;
blackboard.anim.Play("Idle");
}
public void OnExit()
{
}
public void OnUpdate()
{
idleTimer += Time.deltaTime;
if(idleTimer > blackboard.idleTime)
{
fsm.SwitchState(E_StateType.Walk);
}
}
}
public class WalkState : IState
{
private FSM fsm;
private MyBlackboard blackboard;
//构造函数
public WalkState(FSM fSM)
{
this.fsm = fSM;
this.blackboard = fSM.blackboard as MyBlackboard;
}
public void OnEnter()
{
float randomX=Random.Range(-5,5);
blackboard.targetPos = new Vector2(blackboard.transform.position.x+randomX,blackboard.transform.position.y);
blackboard.anim.Play("Walk");
}
public void OnExit()
{
}
public void OnUpdate()
{
if(Vector2.Distance(blackboard.transform.position,blackboard.targetPos)<0.1f)
{
fsm.SwitchState(E_StateType.Idle);
}
else
{
blackboard.transform.position=Vector2.MoveTowards(blackboard.transform.position,blackboard.targetPos,Time.deltaTime*blackboard.moveSpeed);
}
}
}
public class MyAI : MonoBehaviour
{
private FSM fsm;
public MyBlackboard blackboard;
void Start()
{
fsm = new FSM(blackboard);
fsm.AddState(E_StateType.Idle, new IdleState(fsm));
fsm.AddState(E_StateType.Walk, new WalkState(fsm));
fsm.SwitchState(E_StateType.Idle);
}
private void Update()
{
fsm.OnUpdate();
Flip();
}
void Flip()
{
if(blackboard.targetPos!=Vector2.zero)
{
if(blackboard.targetPos.x>blackboard.transform.position.x)
{
transform.localScale=new Vector2(1,1);
}
else
{
transform.localScale=new Vector2(-1,1);
}
}
}
}
标签:必用,AI,blackboard,void,FSM,transform,状态机,public,currentState From: https://blog.csdn.net/Blueberry124/article/details/142423891