FSM控制AI的行为切换,每次切换都通过委托给动画控制器发消息,改变AI的行为与动画。
代码:
FSM管理类:
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;
/// <summary>
/// 遍历字典 测试是使用
/// </summary>
public void Foreach()
{
foreach (var item in states)
{
Debug.Log("System:"+item.Key + "::" + item.Value);
}
}
public void Update(GameObject obj)
{
if (currentState == null)
{
Debug.LogError(currentState+"状态为空");
return;
}
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);
// Debug.Log(id);
if (id == StateID.NullStateID)
{
Debug.LogError("无法根据条件转换");
return;
}
if (states.ContainsKey(id )==false)
{
Debug.LogError(id +"::状态机里不存在该转态,无法转换");
return;
}
FSMState state = states[id];
currentState.DoAdterLeaving();
currentState = state;
currentStateID = id;
currentState.DoBeforEntering();
}
}
FSM基类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <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 int Id;
protected AnimatorStateInfo ani;
protected FSMState(FSMSystem fsm ,Transform trans)
{
Id = trans.GetInstanceID();
//Debug.Log(ani );
this.fsm = fsm;
}
/// <summary>
/// 查错
/// </summary>
public void Foreach()
{
foreach (var item in map)
{
Debug.Log(item.Key + "::" + item.Value);
}
}
/// <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);
}
继承基类的状态:
Idle
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Idel状态
/// </summary>
public class IdelState : FSMState
{
private Transform playerTransform;
public float attackJvLi = 3;
public IdelState(FSMSystem fsm, Transform trans) : base(fsm, trans)
{
stateID = StateID.Idel;
playerTransform = GameObject.FindGameObjectWithTag(StringText.Player).transform;
}
public override void DoBeforEntering()
{
SelectState.Instance.OnEvent(Id, stateID);
// Enemy.Instance.Enemy_Idel();
}
public override void Act(GameObject obj)
{
Quaternion q = Quaternion.LookRotation(playerTransform.position - obj.transform.position);
obj.transform.rotation = Quaternion.Lerp(obj.transform.rotation, q, Time.deltaTime * 5);
}
public override void Reason(GameObject obj)
{
if (Vector3.Angle(obj.transform.forward, playerTransform.position - obj.transform.position) < 20)
{
fsm.PerfromTransition(Transition.AttackPlayer);
}
else if (Vector3.Distance(playerTransform.position, obj.transform.position) > attackJvLi)
{
fsm.PerfromTransition(Transition.LostPlayer);
}
}
}
动画管理器:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 动画状态机管理类
/// </summary>
public class StateMger {
// 定义一个链表来存放人物的所有状态
// 存放人物所能拥有的所有行为状态
private List<StateBase> mStateList = new List<StateBase>();
// 人物所处的状态
public StateBase mCurrentState = null;
/// <summary>
/// 添加状态
/// </summary>
/// <param name="state"></param>
public void AddState(StateBase state)
{
if (!mStateList.Contains(state))
{
mStateList.Add(state);
if (mStateList.Count == 1)
{
mCurrentState = state;
}
}
}
/// <summary>
/// 删除状态
/// </summary>
/// <param name="state"></param>
public void RemoveState(StateBase state) {
if (mStateList.Contains(state))
{
mStateList.Remove(state);
}
}
/// <summary>
/// 更换状态
/// </summary>
/// <param name="state"></param>
public void ChangeState(Type state )
{
foreach(StateBase s in mStateList)
{
if (s.GetType() == state)
{
if (mCurrentState != null)
{
mCurrentState.OnExit();
}
mCurrentState = s;
mCurrentState.OnEnter();
break;
}
}
}
//public void Update()
//{
// mCurrentState.OnUpdate();
//}
}
动画基类:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 状态机基类
/// </summary>
public abstract class StateBase {
// 表示每个状态所影响的那个对象
public Transform transform = null;
public StateBase(Transform transform)
{
this.transform = transform;
}
public abstract void OnEnter();
public abstract void OnUpdate();
public abstract void OnExit();
public static implicit operator StateBase(Type v)
{
throw new NotImplementedException();
}
}
继承动画基类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy_Idle : StateBase {
public Enemy_Idle(Transform transform) : base(transform)
{
}
#region
public override void OnEnter()
{
this.transform.GetComponent<Animator>().SetBool(StringText.Idle, true);
}
public override void OnUpdate()
{
}
public override void OnExit()
{
this.transform.GetComponent<Animator>().SetBool(StringText.Idle, false);
}
#endregion
}
连接两个管理器的单例:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SelectState
{
#region 单例
private static SelectState instance;
public static SelectState Instance
{
get
{
if (instance == null)
{
instance = new SelectState();
}
return instance;
}
}
SelectState() { }
#endregion
//委托字典
Dictionary<int, Enemy> dic = new Dictionary<int, Enemy>();
public void AddInt(int n, Enemy e)
{
//if(!dic .ContainsKey(n))
//{
dic.Add(n, e);
//}
}
/// <summary>
/// 调用
/// </summary>
/// <param name="protoID"></param>
/// <param name="handler"></param>
public void OnEvent(int protoID, StateID state)
{
if (dic.ContainsKey(protoID))
{
switch (state)
{
case StateID.Attack:
dic[protoID].Enemy_Attack();
break;
case StateID.Death:
dic[protoID].Enemy_Deate();
break;
case StateID.Idel:
dic[protoID].Enemy_Idel();
break;
case StateID.Patorl:
dic[protoID].Enemy_Walk();
break;
case StateID.Chase:
dic[protoID].Enemy_Run();
break;
}
}
}
public void OnEvent(int protoID, Transition x)
{
if (dic.ContainsKey(protoID))
{
dic[protoID].fsm.PerfromTransition(x);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SelectState
{
#region 单例
private static SelectState instance;
public static SelectState Instance
{
get
{
if (instance == null)
{
instance = new SelectState();
}
return instance;
}
}
SelectState() { }
#endregion
//委托字典
Dictionary<int, Enemy> dic = new Dictionary<int, Enemy>();
public void AddInt(int n, Enemy e)
{
//if(!dic .ContainsKey(n))
//{
dic.Add(n, e);
//}
}
/// <summary>
/// 调用
/// </summary>
/// <param name="protoID"></param>
/// <param name="handler"></param>
public void OnEvent(int protoID, StateID state)
{
if (dic.ContainsKey(protoID))
{
switch (state)
{
case StateID.Attack:
dic[protoID].Enemy_Attack();
break;
case StateID.Death:
dic[protoID].Enemy_Deate();
break;
case StateID.Idel:
dic[protoID].Enemy_Idel();
break;
case StateID.Patorl:
dic[protoID].Enemy_Walk();
break;
case StateID.Chase:
dic[protoID].Enemy_Run();
break;
}
}
}
public void OnEvent(int protoID, Transition x)
{
if (dic.ContainsKey(protoID))
{
dic[protoID].fsm.PerfromTransition(x);
}
}
}
-------------------------------
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AI_AnimationInit : MonoBehaviour
{
public StateMger m_stateMgr;
/// <summary>
/// 初始化动画状态机
/// </summary>
private void Start()
{
this.GetComponent<Enemy>().Enemy_Walk = OnJoystickDragAction;
this.GetComponent<Enemy>().Enemy_Run = OnRun;
this.GetComponent<Enemy>().Enemy_Attack = OnSkillButonClickAction;
this.GetComponent<Enemy>().Enemy_Deate = Death;
this.GetComponent<Enemy>(). Enemy_Idel = OnJoysticksUPAction;
m_stateMgr = new StateMger();
Enemy_Run run = new Enemy_Run(transform);
m_stateMgr.AddState(run);
Enemy_Idle idle = new Enemy_Idle(transform);
m_stateMgr.AddState(idle);
Enemy_Walk walk = new Enemy_Walk(transform);
m_stateMgr.AddState(walk);
Enemy_Attack attack = new Enemy_Attack(transform);
m_stateMgr.AddState(attack);
Enemy_Death death = new Enemy_Death(transform);
m_stateMgr.AddState(death);
//默认Idle状态
m_stateMgr.ChangeState(typeof(Enemy_Walk));
}
/// <summary>
/// 拖拽时
/// </summary>
/// <param name="coor"></param>
private void OnJoystickDragAction()
{
//Vector3 dir = new Vector3(coor.x, 0, coor.y);
//Quaternion q = Quaternion.LookRotation(dir);
//transform.rotation = Quaternion.Lerp(transform.rotation, q, Time.deltaTime);
// 人物进入RUN状态
m_stateMgr.ChangeState(typeof(Enemy_Walk));
}
/// <summary>
/// 停止移动时
/// </summary>
private void OnJoysticksUPAction()
{
// 人物进入Idle状态
m_stateMgr.ChangeState(typeof(Enemy_Idle));
}
/// <summary>
/// 看见player的时候
/// </summary>
private void OnRun()
{
m_stateMgr.ChangeState(typeof(Enemy_Run));
}
/// <summary>
/// 释放技能时
///
/// </summary>
/// <param name="arg"></param>
private void OnSkillButonClickAction()
{
m_stateMgr.ChangeState(typeof(Enemy_Attack));
}
/// <summary>
/// 挨打动作
/// </summary>
private void OnWound()
{
}
/// <summary>
/// 死亡
/// </summary>
private void Death()
{
m_stateMgr.ChangeState(typeof(Enemy_Death));
}
/// <summary>
/// 持续调用OnUpdate状态
/// </summary>
//private void Update()
//{
// m_stateMgr.Update();
//}
}