FSM 有限状态机

using System.Collections.Generic;
using UnityEngine;

//状态
public enum StateID
{
    Null,   //默认
    Patrol, //巡逻
    Chase   //追逐
}

//条件
public enum Transition
{
    NullTransition,
    FindTarget,
    LostTarget
}
/// 状态类
// 状态ID
// 条件对应状态ID的字典
// 状态机系统
//
// 给字典添加,删除 状态ID,获取状态方法
// 进入,离开状态虚方法,执行,条件虚方法
public abstract class FSMState
{
    protected StateID stateID;
    public StateID ID => stateID;
    protected Dictionary<Transition, StateID> transitionDic = new Dictionary<Transition, StateID>();
    protected FSMSystem fsm;
    public FSMState(FSMSystem fsm) { this.fsm = fsm; }
    //添加条件
    public void AddTransition(Transition transit, StateID sid)
    {
        if (transit == Transition.NullTransition)
        {
            Debug.LogWarning("Transition is null !!!");
            return;
        }
        if (sid == StateID.Null)
        {
            Debug.LogWarning("StateID is null !!!");
            return;
        }
        if (transitionDic.ContainsKey(transit))
        {
            Debug.LogWarning($"{transit} already exists in the Dictionary !!!");
            return;
        }
        transitionDic.Add(transit, sid);
    }
    //删除条件
    public void Remove(Transition transit)
    {
        if (transit == Transition.NullTransition)
        {
            Debug.LogWarning("Transition is null !!!");
            return;
        }
        if (!transitionDic.ContainsKey(transit))
        {
            Debug.LogWarning($"{transit} is not found in Dictionary !!!");
            return;
        }
        transitionDic.Remove(transit);
    }
    //根据条件获取状态ID
    public StateID GetStateID(Transition transit)
    {
        if (transitionDic.ContainsKey(transit))
        {
            return transitionDic[transit];
        }
        return StateID.Null;
    }
    //进入状态
    public virtual void Entering() { }
    //离开状态
    public virtual void Leaving() { }
    //执行状态
    public virtual void Executing(GameObject go) { }
    //判断条件状态
    public virtual void Reason(GameObject go) { }
}
using System.Collections.Generic;
using UnityEngine;

public class FSMSystem
{
    protected FSMState currentState;
    protected StateID currentID;
    protected Dictionary<StateID, FSMState> statedic = new Dictionary<StateID, FSMState>();
    public void Update(GameObject go)
    {
        currentState.Executing(go);
        currentState.Reason(go);
    }
    //添加状态
    public void AddState(FSMState state)
    {
        if (state is null)
        {
            Debug.LogWarning("state is null !!!");
            return;
        }
        if (currentState is null)
        {
            currentState = state;
            currentID = state.ID;
        }
        if (state.ID == StateID.Null)
        {
            Debug.LogWarning("state ID is null !!!");
            return;
        }
        statedic.Add(state.ID, state);
    }
    //删除状态
    public void RemoveState(FSMState state)
    {
        if (state is null)
        {
            Debug.LogWarning("state is null !!!");
            return;
        }
        var stateID = state.ID;

        if (stateID == StateID.Null)
        {
            Debug.LogWarning("stateID is null !!!");
            return;
        }
        if (!statedic.ContainsKey(stateID))
        {
            Debug.LogWarning("stateID is not found in stateDic !!!");
            return;
        }
        statedic.Remove(stateID);
    }
    //进入下一状态
    //获取状态,离开当前(上一个)状态,修改当前状态 进入新状态
    public void PreformTransition(Transition transit)
    {
        if (transit is Transition.NullTransition)
        {
            Debug.LogWarning("transit is NullTransition !!!");
            return;
        }
        var stateID = currentState.GetStateID(transit);
        if (stateID == StateID.Null)
        {
            Debug.LogWarning("stateID si NUll");
            return;
        }
        if (!statedic.ContainsKey(stateID))
        {
            Debug.LogWarning("stateID is not found in stateDic");
            return;
        }
        FSMState state = statedic[stateID];
        currentState.Leaving();
        currentState = state;
        currentID = stateID;
        currentState.Entering();
    }
}
using System.Collections.Generic;
using UnityEngine;
//巡逻状态
public class PaterState : FSMState
{
    private List<Transform> path = new List<Transform>();
    private int index = 0;
    private Transform player;
    public PaterState(FSMSystem fsm) : base(fsm)
    {
        stateID = StateID.Patrol;
        Transform path = GameObject.Find("Path").transform;
        player = GameObject.Find("Player").transform;
        Transform[] childrens = path.GetComponentsInChildren<Transform>();
        foreach (var children in childrens)
        {
            if (children != path)
            {
                this.path.Add(children);
            }
        }
    }
    public override void Executing(GameObject go)
    {
        go.transform.LookAt(path[index].position);
        go.transform.Translate(go.transform.forward * 3 * Time.deltaTime, Space.World);
        if (Vector3.Distance(go.transform.position, path[index].position) < 1)
        {
            ++index;
            index %= this.path.Count;
        }
    }
    public override void Reason(GameObject go)
    {
        var angle = Vector3.Angle(go.transform.forward, player.position - go.transform.position);
        var distance = Vector3.Distance(go.transform.position, player.transform.position);
        if (angle <= 60 && distance < 3)
        {
            fsm.PreformTransition(Transition.FindTarget);
        }
    }
}
using UnityEngine;
//追逐状态
public class ChaseState : FSMState
{
    private Transform player;
    public ChaseState(FSMSystem fsm) : base(fsm)
    {
        stateID = StateID.Chase;
        player = GameObject.Find("Player").transform;
    }
    public override void Executing(GameObject go)
    {
        go.transform.LookAt(player);
        if (Vector3.Distance(go.transform.position, player.position) < 1) return;
        go.transform.Translate(go.transform.forward * 3 * Time.deltaTime, Space.World);
    }
    public override void Reason(GameObject go)
    {
        if (Vector3.Distance(go.transform.position, player.position) > 8)
        {
            fsm.PreformTransition(Transition.LostTarget);
        }
    }
}
using UnityEngine;
//敌人
public class Enemy : MonoBehaviour
{
    private FSMSystem fsm;
    private void Start() { InitFSM(); }
    void Update() { fsm.Update(gameObject); }
    void InitFSM()
    {
        fsm = new FSMSystem();
        FSMState patrolState = new PaterState(fsm);
        patrolState.AddTransition(Transition.FindTarget, StateID.Chase);

        FSMState chaseState = new ChaseState(fsm);
        chaseState.AddTransition(Transition.LostTarget, StateID.Patrol);

        fsm.AddState(patrolState);
        fsm.AddState(chaseState);
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值