UI框架---FSM(简化版有限状态机)

目前包括脚本:FSMState,PatrolState,ChaseState,AttackState  / FSMSystem /Enemy

备注:其中 Animator.SetInteger("action",n)     是我自己给Monster做的动画状态,用于切换;

           代码中多处判断是否为Null,是为了开发中避免极小概率事件的发生,防止游戏奔溃做的处理。

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum Transition
{
	NullTransition=0,
	SeePlayer,
	LostPlayer,
    AttackPlayer
}
public enum StateID
{
	NullStateID=0,
	Patrol,
	Chase,
    Attack

}


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;
        Debug.Log(stateID);
	}


	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 + "已经存在于map中");return;
		}
		map.Add(trans, id);
	}
	public void DeleteTransition(Transition trans)
	{
		if (trans == Transition.NullTransition)
		{
			Debug.LogError("不允许NullTransition"); return;
		}
		if (map.ContainsKey(trans)==false)
		{
			Debug.LogError("删除转换条件的时候," + trans + "不存在于map中"); 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 Act(GameObject npc);
	public abstract void Reason(GameObject npc);
}

 

using System.Collections;
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.Act(npc);
		currentState.Reason(npc);
	}

	public void AddState(FSMState s)
	{
		if (s == null)
		{
			Debug.LogError("FSMState不能为空");return;
		}
		if (currentState == null)
		{
			currentState = s;
			currentStateID = s.ID;
		}
		if (states.ContainsKey(s.ID))
		{
			Debug.LogError("状态" + s.ID + "已经存在,无法重复添加");return;
		}
		states.Add(s.ID, s);
	}
	public void DeleteState(StateID id)
	{
		if (id == StateID.NullStateID)
		{
			Debug.LogError("无法删除空状态");return;
		}
		if (states.ContainsKey(id) == false)
		{
			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.LogWarning("当前状态" + currentStateID + "无法根据转换条件" + trans + "发生转换");return;
		}
		if (states.ContainsKey(id) == false)
		{
			Debug.LogError("在状态机里面不存在状态" + id + ",无法进行状态转换!");return;
		}
		FSMState state = states[id];
		currentState.DoAfterLeaving();
		currentState = state;
		currentStateID = id;
		currentState.DoBeforeEntering();
	}
} 
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChaseState : FSMState
{
	private Transform playerTransform;
	public ChaseState(FSMSystem fsm) : base(fsm)
	{
		stateID = StateID.Chase;
		playerTransform = GameObject.Find("Boy").transform;
	}

	public override void Act(GameObject npc)
	{
        Animator ani = npc.transform.GetComponent<Animator>();
        ani.SetInteger("action", 1);
        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) > 10)
		{
			fsm.PerformTransition(Transition.LostPlayer);
		}
        if (Vector3.Distance(playerTransform.position,npc.transform.position)<1)
        {
            fsm.PerformTransition(Transition.AttackPlayer);
        }
	}
}
using System;
using System.Collections;
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("Boy").transform;
	}

	public override void Act(GameObject npc)
	{
		npc.transform.LookAt(path[index].position);
		npc.transform.Translate(Vector3.forward * Time.deltaTime * 3);
        Animator ani =  npc.transform.GetComponent<Animator>();
        ani.SetInteger("action", 1);
		if (Vector3.Distance(npc.transform.position, path[index].position) < 1)
		{
            //index++;
            //index %= path.Count;
            //index = new System.Random().Next(path.Count);
            index = UnityEngine.Random.Range(0,path.Count);
		}
	}

	public override void Reason(GameObject npc)
	{
		if (Vector3.Distance(playerTransform.position, npc.transform.position) < 6)
		{
			fsm.PerformTransition(Transition.SeePlayer);
		}
	}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AttackState : FSMState {

    private Transform playerTransform;
    Animator m_aniMonster;
    public AttackState(FSMSystem fsm) : base(fsm)
    {
        stateID = StateID.Attack;
        playerTransform = GameObject.Find("Boy").transform;
    }

    public override void Act(GameObject npc)
    {
        m_aniMonster = npc.transform.GetComponent<Animator>();
        m_aniMonster.SetInteger("action", 2);
        
        npc.transform.LookAt(playerTransform.position);

        
    }
    public override void Reason(GameObject npc)
    {
        if (Vector3.Distance(playerTransform.position, npc.transform.position) > 1)
        {
            fsm.PerformTransition(Transition.SeePlayer);
        }
    }
    
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour {

	private FSMSystem fsm;

	void Start () {
		InitFSM();
	}

	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);
        chaseState.AddTransition(Transition.AttackPlayer, StateID.Attack);

        FSMState attackState = new AttackState(fsm);
        attackState.AddTransition(Transition.SeePlayer, StateID.Chase);

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

	void Update () {
		fsm.Update(this.gameObject);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值