有限状态基(FSM)

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");
            }
            
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值