管理類:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 管理類
/// </summary>
public class FSMSystem {
public Dictionary<StateID, FSMState> states = new Dictionary<StateID, FSMState>();
private StateID currentStateID;
private FSMState currentState;
public void Update(GameObject obj)
{
currentState.Act(obj);
currentState.Reason(obj);
}
/// <summary>
/// 添加狀態
/// </summary>
/// <param name="s">狀態</param>
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("該狀態已存在");
return;
}
states.Add(s.ID, s);
}
/// <summary>
/// 狀態刪除
/// </summary>
/// <param name="id"></param>
public void DelegateState(StateID id)
{
if(id ==StateID .NullStateID)
{
Debug.LogError("無法刪除空狀態");
return;
}
if (states .ContainsKey (id )==false)
{
Debug.LogError("無法刪除不存在的狀態");
return;
}
states.Remove(id);
}
/// <summary>
/// 狀態轉換
/// </summary>
/// <param name="trans"></param>
public void PerfromTransition(Transition trans)
{
if(trans==Transition.NullTransition)
{
Debug.LogError("空的轉換條件");
return;
}
StateID id = currentState.GetOutputState(trans);
if (id == StateID.NullStateID)
{
Debug.LogError("無法根據條件轉換");
return;
}
if (states.ContainsKey(id )==false)
{
Debug.LogError("狀態機裏不存在該轉態,無法轉換");
return;
}
FSMState state = states[id];
currentState.DoAdterLeaving();
currentState = state;
currentStateID = id;
currentState.DoBeforEntering();
}
}
基類:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Transition
{
NullTransition=0,
/// <summary>
/// 看見主角
/// </summary>
SeePlayer,
/// <summary>
/// 主角消失
/// </summary>
LostPlayer
}
public enum StateID
{
NullStateID=0,
/// <summary>
/// 巡邏
/// </summary>
Patorl,
/// <summary>
/// 追逐主角
/// </summary>
Chase
}
/// <summary>
/// 狀態基類
/// </summary>
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;
protected FSMState(FSMSystem fsm )
{
this.fsm = fsm;
}
/// <summary>
/// 添加狀態
/// </summary>
/// <param name="trans"></param>
/// <param name="id"></param>
public void Addtransition(Transition trans,StateID id)
{
if (trans == Transition.NullTransition)
{
Debug.LogError("不允許NullTransition");
return;
}
if (id == StateID .NullStateID)
{
Debug.LogError("不允許Nullstate");
return;
}
if (map .ContainsKey (trans ))
{
Debug.LogError("已存在");
return;
}
map.Add(trans, id);
}
/// <summary>
/// 刪除狀態
/// </summary>
/// <param name="trans"></param>
public void DeleteTransition(Transition trans)
{
if (trans == Transition.NullTransition)
{
Debug.LogError("不允許NullTransition");
return;
}
if (map.ContainsKey(trans)==false )
{
Debug.LogError("不存在");
return;
}
map.Remove(trans);
}
/// <summary>
/// 判斷當前狀態
/// </summary>
/// <param name="trans"></param>
/// <returns></returns>
public StateID GetOutputState(Transition trans)
{
if (map.ContainsKey (trans))
{
return map[trans];
}
return StateID.NullStateID;
}
/// <summary>
/// 進入狀態之前所做的狀態
/// </summary>
public virtual void DoBeforEntering() { }
/// <summary>
/// 離開狀態的時候
/// </summary>
public virtual void DoAdterLeaving() { }
/// <summary>
/// 在當前狀態下要做的事情
/// </summary>
public abstract void Act(GameObject obj);
/// <summary>
/// 判斷轉換條件
/// </summary>
public abstract void Reason(GameObject obj);
}
兩個AI狀態:1
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 巡邏狀態
/// </summary>
public class PatrolState : FSMState
{
private List <Transform > path=new List<Transform> ();
private int index = 0;
private Transform playerTransform;
public float jvLi = 3;
public PatrolState (FSMSystem fsm):base (fsm)
{
stateID = StateID.Patorl;
Transform pathTransform = GameObject.Find("Path").transform;
Transform[] children = pathTransform.GetComponentsInChildren<Transform > ();
foreach (Transform item in children )
{
if (item !=pathTransform)
{
path.Add(item);
}
}
playerTransform = GameObject.FindGameObjectWithTag(StringText .Player ).transform;
}
/// <summary>
/// 處於當前狀態時要做的事
/// </summary>
/// <param name="obj"></param>
public override void Act(GameObject obj)
{
obj.transform.LookAt(path[index].position );
obj.transform.Translate(Vector3.forward * Time.deltaTime * 2);
if (Vector3 .Distance (obj.transform .position ,path[index ].position) < 0.5f)
{
index++;
index %= path.Count;
}
}
/// <summary>
/// 判斷轉換條件
/// </summary>
/// <param name="obj"></param>
public override void Reason(GameObject obj)
{
//throw new System.NotImplementedException();
if (Vector3 .Distance (playerTransform .position ,obj .transform .position) < jvLi )
{
fsm.PerfromTransition(Transition.SeePlayer);
}
}
}
2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 追逐Player
/// </summary>
public class ChaseState : FSMState
{
public float speed = 2;
private Transform playerTransform;
private float jvLi=6;
public ChaseState(FSMSystem fsm) : base(fsm)
{
stateID = StateID.Chase;
playerTransform = GameObject.FindGameObjectWithTag(StringText.Player).transform;
}
public override void Act(GameObject obj)
{
obj.transform.LookAt(playerTransform.position);
obj.transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
public override void Reason(GameObject obj)
{
if (Vector3.Distance(playerTransform.position, obj.transform.position) > jvLi)
{
fsm.PerfromTransition(Transition.LostPlayer);
}
}
}
調用:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 敵人
/// </summary>
public class Enemy : MonoBehaviour {
FSMSystem fsm;
void Start () {
fsm = new FSMSystem();
FSMState patrolState = new PatrolState(fsm);
patrolState.Addtransition(Transition.SeePlayer, StateID.Chase);
FSMState chaseState = new ChaseState(fsm);
chaseState.Addtransition(Transition.LostPlayer, StateID.Patorl);
fsm.AddState(patrolState);
fsm.AddState(chaseState);
}
void Update () {
fsm.Update(this.gameObject);
}
}