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);
}
}