FSM 和动画管理器做的AI

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






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值