1.状态基接口
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface IFSMNode
{
public abstract void Enter();//根据需要传所需的参数——可写成泛型
public abstract void Exit();
public abstract void Update();
}
2.状态基管理类
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FSMManager
{
Dictionary<string,IFSMNode> allStateNode=new Dictionary<string,IFSMNode>();//存储所有的节点
IFSMNode currentNode;//当前的节点
/// <summary>
/// 添加节点
/// </summary>
/// <param name="name">节点名称</param>
/// <param name="node">节点</param>
/// <returns>是否添加成功</returns>
public bool AddNode(string name, IFSMNode node)
{
if(allStateNode.ContainsKey(name))
{
return true;
}
allStateNode.Add(name, node);
return true;
}
/// <summary>
/// 运行节点
/// </summary>
/// <param name="name">节点的名称</param>
/// <returns>是否运行成功</returns>
public bool RunNode(string name)
{
if(!allStateNode.ContainsKey(name))
{
return false;
}
if(currentNode!=null)
{
currentNode.Exit();
}
currentNode = allStateNode[name];
currentNode.Enter();//调用泛型方法
return true;
}
/// <summary>
/// 进入节点
/// </summary>
/// <param name="tarrget"></param>
public void Enter(Transform tarrget)
{
if (currentNode != null)
{
currentNode.Enter();
}
}
/// <summary>
/// 调用节点中的更新方法
/// </summary>
public void Update()
{
if(currentNode != null)
{
currentNode.Update();
}
}
/// <summary>
/// 调用节点中的离开方法
/// </summary>
public void Exit()
{
if(currentNode != null)
{
currentNode.Exit();
}
}
/// <summary>
/// 判断是否是当前节点
/// </summary>
/// <param name="v"></param>
/// <returns></returns>
internal bool IsCurrentNode(string v)
{
if(currentNode!=null)
{
if(currentNode== allStateNode[v])
{
return true ;
}
}
return false;
}
}
3.随机巡逻——其他状态的格式也是如此
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static UnityEngine.GraphicsBuffer;
public class RunNode : IFSMNode
{
Vector3 desPos;
Transform myselfTrans;
public RunNode(GameObject gameObject)
{
this.myselfTrans = gameObject.transform;
}
public void Exit()
{
}
/// <summary>
/// 随机位置巡逻
/// </summary>
public void Update()
{
float dis = Vector3.Distance(desPos, myselfTrans.position);
Debug.DrawLine(desPos, myselfTrans.position);
if (dis < 2)
{
Vector2 v2 = Random.insideUnitCircle * 10;
desPos = new Vector3(v2.x, myselfTrans.position.y, v2.y);
myselfTrans.LookAt(desPos);
}
else
{
myselfTrans.Translate(Vector3.forward * 10 * Time.deltaTime);
}
}
/// <summary>
/// 进入方法
/// </summary>
public void Enter()
{
//随机位置
Vector2 v2 = Random.insideUnitCircle * 10;
desPos = new Vector3(v2.x, myselfTrans.position.y, v2.y);
myselfTrans.LookAt(desPos);
}
}
4.追击
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PursueNode : IFSMNode
{
Transform targetTrans;//追击的玩家
Transform myselfTrans;//自己
public PursueNode(GameObject gameObject, GameObject player)
{
this.myselfTrans = gameObject.transform;
this.targetTrans= player.transform;
}
public void Enter()
{
}
public void Exit()
{
}
public void Update()
{
myselfTrans.LookAt(targetTrans);
myselfTrans.Translate(Vector3.forward * 10 * Time.deltaTime);
}
}
5.调用状态基——示例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyFSM : MonoBehaviour
{
FSMManager fsmManager=new FSMManager();//状态机管理类
GameObject player;
private void Start()
{
player = GameObject.FindGameObjectWithTag("Player");
//添加状态
this.fsmManager.AddNode("Run", new RunNode(gameObject));
this.fsmManager.AddNode("Pursue", new PursueNode(gameObject,player));
//运行状态
Run("Run");
}
/// <summary>
/// 通过名称运行对应的状态
/// </summary>
/// <param name="name"></param>
public void Run(string name)
{
this.fsmManager.RunNode(name);
}
/// <summary>
/// 调用状态基的更新方法
/// </summary>
private void Update()
{
this.fsmManager.Update();
if(Vector3.Distance(transform.position, player.transform.position)<5)
{
if(!this.fsmManager.IsCurrentNode("Pursue"))
{
Run("Pursue");
}
}
else
{
if (!this.fsmManager.IsCurrentNode("Run"))
{
Run("Run");
}
}
}
}