FSM有限状态机

FSM有限状态机

首先是状态机入口

using UnityEngine;

public class Enemy : MonoBehaviour
{
    private FSMSystem fsm;

    private void Start()
    {
        InitFSM();
    }

    private void InitFSM()
    {
        fsm = new FSMSystem();
        FSMState patrolState = new PatrolState(fsm);
        patrolState.AddTransition(Transition.SeePlayer, StateID.Chase);

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

        fsm.AddState(patrolState);
        fsm.AddState(chaseState);
    }
    private void Update()
    {
        fsm.Update(gameObject);
    }
}

然后是状态机类

using System.Collections.Generic;
using UnityEngine;

public class FSMSystem
{
    private Dictionary<StateID, FSMState> states = new Dictionary<StateID, FSMState>();
    private StateID currentStateID;
    private FSMState currentState;

    public void Update(GameObject npc)
    {
        currentState.Action(npc);
        currentState.Reason(npc);
    }

    public void AddState(FSMState state)
    {
        if (state == null)
        {
            Debug.LogError("FSMState不能为空"); return;
        }
        if (currentState == null)
        {
            currentState = state;
            currentStateID = state.ID;
        }
        if (states.ContainsKey(state.ID))
        {
            Debug.LogError("状态" + state.ID + "已经存在,无法重复添加"); return;
        }
        states.Add(state.ID, state);
    }

    public void DeleteState(StateID id)
    {
        if (id == StateID.NullStateID)
        {
            Debug.LogError("无法删除空状态"); return;
        }
        if (!states.ContainsKey(id))
        {
            Debug.LogError("状态不存在,无法删除" + id); return;
        }
        states.Remove(id);
    }

    public void PerformTransition(Transition trans)
    {
        if (trans == Transition.NullTransition)
        {
            Debug.LogError("无法执行空的转换条件"); return;
        }
        StateID id = currentState.GetOutputState(trans);
        if (id == StateID.NullStateID)
        {
            Debug.LogError("当前状态" + currentStateID + "无法根据转换条件" + trans + "发生转换"); return;
        }
        if (!states.ContainsKey(id))
        {
            Debug.LogError("状态机里不存在状态" + id + ",无法进行状态转换"); return;
        }
        FSMState state = states[id];
        currentState.DoAfterLeaving();
        currentState = state;
        currentStateID = id;
        currentState.DoBeforeEntering();
    }
}

状态的父类

using System.Collections.Generic;
using UnityEngine;

public enum Transition
{
    NullTransition = 0,
    SeePlayer,
    LostPlayer
}

public enum StateID
{
    NullStateID = 0,
    Patrol,
    Chase
}

public abstract class FSMState
{
    protected StateID stateID;
    public StateID ID { get { return stateID; } }
    protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();
    protected FSMSystem fsm;

    public FSMState(FSMSystem fsm)
    {
        this.fsm = fsm;
    }

    public void AddTransition(Transition trans, StateID id)
    {
        if (trans == Transition.NullTransition)
        {
            Debug.LogError("不允许NullTransition"); return;
        }
        if (id == StateID.NullStateID)
        {
            Debug.LogError("不允许NullStateID"); return;
        }
        if (map.ContainsKey(trans))
        {
            Debug.LogError("已经存在该条件" + trans); return;
        }
        map.Add(trans, id);
    }
    public void DeleteTransition(Transition trans)
    {
        if (trans == Transition.NullTransition)
        {
            Debug.LogError("不允许NullTransition"); return;
        }
        if (!map.ContainsKey(trans))
        {
            Debug.LogError("不存在该条件" + trans); return;
        }
        map.Remove(trans);
    }

    public StateID GetOutputState(Transition trans)
    {
        if (map.ContainsKey(trans))
        {
            return map[trans];
        }
        return StateID.NullStateID;
    }

    public virtual void DoBeforeEntering() { }
    public virtual void DoAfterLeaving() { }
    public abstract void Action(GameObject npc);
    public abstract void Reason(GameObject npc);
}

巡逻状态

using System.Collections.Generic;
using UnityEngine;

public class PatrolState : FSMState
{
    private List<Transform> path = new List<Transform>();
    private int index = 0;
    private Transform playerTransform;

    public PatrolState(FSMSystem fsm) : base(fsm)
    {
        stateID = StateID.Patrol;
        Transform pathTransform = GameObject.Find("Path").transform;
        Transform[] children = pathTransform.GetComponentsInChildren<Transform>();
        foreach (Transform child in children)
        {
            if (child != pathTransform)
            {
                path.Add(child);
            }
        }
        playerTransform = GameObject.Find("Player").transform;
    }
    public override void Action(GameObject npc)
    {
        npc.transform.LookAt(path[index].position);
        npc.transform.Translate(Vector3.forward * Time.deltaTime * 3);
        if (Vector3.Distance(npc.transform.position, path[index].position) < 1)
        {
            index++;
            index %= path.Count;
        }
    }

    public override void Reason(GameObject npc)
    {
        if (Vector3.Distance(playerTransform.position, npc.transform.position) < 3)
        {
            fsm.PerformTransition(Transition.SeePlayer);
        }
    }
}

追击状态

using UnityEngine;

public class ChaseState : FSMState
{
    private Transform playerTransform;

    public ChaseState(FSMSystem fsm) : base(fsm)
    {
        stateID = StateID.Chase;
        playerTransform = GameObject.Find("Player").transform;
    }

    public override void Action(GameObject npc)
    {
        npc.transform.LookAt(playerTransform.position);
        npc.transform.Translate(Vector3.forward * 2 * Time.deltaTime);
    }

    public override void Reason(GameObject npc)
    {
        if (Vector3.Distance(playerTransform.position, npc.transform.position) > 6)
        {
            fsm.PerformTransition(Transition.LostPlayer);
        }
    }
}

结束语:重点是学习代码的框架和管理思想,以后研究HFSM

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值