1,最笨的方法实现状态机
(不容易维护 没有吧各个方法独立出来 添加新状态还要从新修改代码)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SimpleFSM : MonoBehaviour {
public enum State
{
Idel,//闲置
Patrol,//巡逻
Chase,//追
Attack,//打
}
void Start () {
}
private void ProcessStateIdle()
{
}
private void ProcessStatePatrol()
{
}
private void ProcessStateChase()
{
}
private void ProcessStateAttack()
{
}
private State state = State.Idel;
void Update () {
switch (state)
{
case State.Idel:
ProcessStateIdle();
break;
case State.Patrol:
ProcessStatePatrol();
break;
case State.Chase:
ProcessStateChase();
break;
case State.Attack:
ProcessStateAttack();
break;
default:
break;
}
}
}
2,创建状态机核心类FSMState
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Transition
{
NullTransition=0,
SeePlayer,
LosePlayer,
}
public enum StateID
{
NullStateID=0,
Patrol,//巡逻
Chease,//跟踪
}
public abstract class FSMState {
public Transform CubeTranform;
protected FSMSystem FSMSysyem;
protected FSMState(FSMSystem FSMSysyem)
{
CubeTranform = GameObject.Find("Cube").transform;
this.FSMSysyem = FSMSysyem;
}
protected StateID stateID;
public StateID ID { get { return stateID; } }
protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();
public void AddTransition(Transition transition,StateID stateID)
{
if (transition==Transition.NullTransition)
{
Debug.Log("NullTransition为"); return;
}
if (stateID==StateID.NullStateID)
{
Debug.Log("NullStateID"); return;
}
if (map.ContainsKey(transition))
{
Debug.Log("Map 已经存在了transition:" + transition); return;
}
// Debug.Log("map "+ transition+" "+ stateID);
map.Add(transition, stateID);
}
public void RemoveTransition(Transition transition )
{
if (transition == Transition.NullTransition)
{
Debug.Log("NullTransition为"); return;
}
if (stateID == StateID.NullStateID)
{
Debug.Log("NullStateID"); return;
}
if (map.ContainsKey(transition)==false)
{
Debug.Log("transition不存在当前map中");
}
map.Remove(transition);
}
public StateID GetOutPutState(Transition transition)
{
if (map.ContainsKey(transition)==false)
{
Debug.Log("没有要转变的状态");
return StateID.NullStateID;
}
return map[transition];
}
public virtual void DoBeforeEntering() { }
public virtual void DOAdterLeaving() { }
public abstract void Act(GameObject npc);
public abstract void Reason(GameObject npc); //判断转换条件
}
开发管理类 FSMSystem
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FSMSystem {
private Dictionary<StateID, FSMState> states=new Dictionary<StateID, FSMState>();
public FSMState currentState;
private StateID currentID;
// public FSMState FSMStete { get { return currentState; } }
public void Update(GameObject npc)
{
currentState.Act(npc);
currentState.Reason(npc);
}
public void AddState(FSMState fSMStete)
{
if (fSMStete==null)
{
Debug.Log("fSMStete为空 不能进行添加"); return;
}
if (currentState==null)
{
currentState = fSMStete;
currentID = fSMStete.ID;
}
if (states.ContainsKey(fSMStete.ID))
{
Debug.Log("状态" + fSMStete.ID + "已经存在 不让重复添加"); return;
}
// Debug.Log(fSMStete);
states.Add(fSMStete.ID, fSMStete);
}
private void Delete(StateID id)
{
if (id ==StateID.NullStateID)
{
Debug.Log("fSMStete为空 不能进行添加"); return;
}
if (states.ContainsKey(id))
{
Debug.Log("无法删除一个不存在的ID:" + id); return;
}
states.Remove(id);
}
public void PerformTransition(Transition transition)
{
if (transition==Transition.NullTransition)
{
Debug.Log("无法执行空的转换条件NullTransition"); return;
}
StateID stateID = currentState.GetOutPutState(transition);
if (stateID==StateID.NullStateID)
{
Debug.Log("不需要发生转换"+ stateID ); return;
}
if (states.ContainsKey(stateID)==false)
{
Debug.Log("在状态机里面 不包含状态" + stateID+"无法进行转换"); return;
}
FSMState state = states[stateID];
state.DOAdterLeaving();
currentState = state;
currentID = stateID;
state.DoBeforeEntering();
}
}
开发巡逻状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PatrolState : FSMState {
public List<Transform >path =new List<Transform>();
private int index = 0;
public PatrolState(FSMSystem fSMSystem):base(fSMSystem)
{
stateID = StateID.Patrol;
GameObject pathGameobject = GameObject.Find("Path");
Transform[] pathchildren = pathGameobject.GetComponentsInChildren<Transform>();
foreach (Transform item in pathchildren)
{
if (item != pathGameobject.transform)
{
path.Add(item);
}
}
}
public override void Act(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( CubeTranform.position,npc.transform.position)<3 )
{
FSMSysyem.PerformTransition(Transition.SeePlayer);
}
}
}
开发跟踪状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ChaseState :FSMState {
public ChaseState(FSMSystem fSMSystem):base(fSMSystem)
{
stateID = StateID.Chease;
}
public override void Act(GameObject npc)
{
npc.transform.LookAt(CubeTranform);
npc.transform.Translate(Vector3.forward * 2 * Time.deltaTime);
}
public override void Reason(GameObject npc)
{
if (Vector3.Distance(CubeTranform.position, npc.transform.position) >5)
{
FSMSysyem.PerformTransition(Transition.LosePlayer);
}
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
AI敌人 脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour {
private FSMSystem fSMSystem;
void Start () {
InitFsmSystem();
}
void Update () {
fSMSystem.Update(this.gameObject);
}
void InitFsmSystem()
{
fSMSystem = new FSMSystem();
FSMState patrolState = new PatrolState(fSMSystem);
patrolState.AddTransition(Transition.SeePlayer, StateID.Chease);
fSMSystem.AddState(patrolState);
FSMState chaseState = new ChaseState(fSMSystem);
chaseState.AddTransition(Transition.LosePlayer, StateID.Patrol);
fSMSystem.AddState(chaseState);
}
}