unity怪物的状态机

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public enum StateType:byte
{
    Follow, //追踪
    Attack,  //攻击
    Partrol,//巡逻
    Death //死亡
}


///
/// 所有的具体状态都实现这个接口
///

public interface IState
{
    FSM fsm { get; set; } //所属的状态机

    StateType stateType { get; }  /// 状态类型。

    void EnterState(); //状态进入

    void StateUpdate(float deltaTime); ///状态更新

    void StateLateUpdate(float deltaTime);

    void ExitState(); //状态退出
}

**************************************************************************************************************



using System;
using System.Collections.Generic;
using UnityEngine;

///


/// 状态机类,管理各个状态实例。
/// 作用
/// 1.把能够切换管理的各个状态注册到状态机里。
///  2.移除状态
/// 3.在各个状态间切换的逻辑
/// 4.不断的更新当前状态
///
///
///
///  通俗点讲,
///  1.有限状态机是:将对象的状态(攻击、闲置、晕眩)的实现代码,提取出来,封装成状态。
///    由状态机负责在各个状态之间调度。
//   2 .对象(AI对象)持有状态管理类(状态机)的引用,与具体的状态解耦
///


public class FSM
{
    private Dictionary stateDic;

    //当前状态
    private IState currentState;

    private GameObject role;  //关联一个游戏兑现(AI对象)
    public GameObject Role
    {
        get { return role; }
    }

    public FSM(GameObject role)
    {
        this.role = role;
        stateDic = new Dictionary();
    }



    //注册状态
    ///
    /// 只有注册过的状态才可以被切换
    ///

    ///
    public void registerState(IState state)
    {
        IState s;
        stateDic.TryGetValue(state.stateType, out s);
        if (s == null)
        {
            state.fsm = this;
            stateDic.Add(state.stateType, state);
        }
        else
        {
            Debug.Log("已经有" + state.stateType + "了,不可以重复注册");
        }

    }
    ///
    ///
    ///

    ///
    public void removeState(StateType stateType)
    {
        if (currentState.stateType != stateType)
        {
            IState s;
            stateDic.TryGetValue(stateType, out s);
            if (s != null)
            {
                stateDic.Remove(stateType);
            }
            else
            {
                Debug.Log(stateType + "还没有注册,移除失败。");
            }
        }
        else
        {
            Debug.Log(stateType + "是当前状态,移除失败。");
        }

    }

    ///
    /// 切换状态
    /// 1.退出之前状态
    /// 2.进入要进入的状态
    ///

    /// 要进入的状态的类型。
    public void changeState(StateType type)
    {
        IState s;
        stateDic.TryGetValue(type, out s);
        if (s != null)
        {
            if (currentState != null)
                currentState.ExitState();//退出之前的状态

            s.EnterState(); ///进入状态,
            currentState = s;///当前状态更改为已经进入的状态
        }
        else
        {
            Debug.Log(type + "还没有被注册进状态机");
        }
    }

    //更新当前状态
    public void Update(float deltaTime)
    {
        if (currentState != null)
        {
            currentState.StateUpdate(deltaTime);
        }
    }

    public void LateUpdate(float deltaTime)
    {
        if (currentState != null)
        {
            currentState.StateLateUpdate(deltaTime);
        }
    }
}

***************************************************************************************************

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MonsterController : MonoBehaviour
{

    //此怪物的的状态机
    private FSM fsm;
    [SerializeField]
    private GameObject fxPrefab;
    private void Awake()
    {
        fsm = new FSM(this.gameObject);
        fsm.registerState(new FollowState());
        fsm.registerState(new AttackState());
        fsm.registerState(new PartrolState());
        fsm.registerState(new DeathState());
        fsm.changeState(StateType.Partrol);

    }

    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        ///更新状态机
        if (fsm != null)
        {
            fsm.Update(Time.deltaTime);
        }

    }

    private void LateUpdate()
    {
        if(fsm!=null)
        {
            fsm.LateUpdate(Time.deltaTime);
        }
    }
    ///


    /// 死亡后调用此方法。
    ///

    public void OnDeath()
    {
        GameObject fx = GameObject.Instantiate(fxPrefab);
        fx.transform.position = this.transform.position + new Vector3(0, 0.6f, 0);
        this.fsm.changeState(StateType.Death);
    }

    public void OnDefeat()
    {
        this.GetComponent().SetTrigger("defeat");
        GameObject fx = GameObject.Instantiate(fxPrefab);
        fx.transform.position = this.transform.position+new Vector3(0,0.6f,0);

    }


}
*******************************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

public class DeathState : IState
{
    public FSM fsm
    {
        get;set;
    }

    public StateType stateType
    {
        get { return StateType.Death; }
    }

    public void EnterState()
    {
        this.fsm.Role.GetComponent().SetTrigger("death");
    }

    public void ExitState()
    {
        
    }

    public void StateLateUpdate(float deltaTime)
    {
        
    }

    public void StateUpdate(float deltaTime)
    {
        AnimatorStateInfo stateinfo = this.fsm.Role.GetComponent().GetCurrentAnimatorStateInfo(0);
        if(stateinfo.IsName("Death")&&stateinfo.normalizedTime%1>0.95f)
        {
            GameObject.Destroy(this.fsm.Role);
            SpawnEnemy.Instance.EnemyList.Remove(this.fsm.Role);
        }
    }
}
 
**********************************************************************************************************************************
using UnityEngine;
using UnityEngine.AI;

public class FollowState : IState
{
    private GameObject targetObj; //玩家

    /// =========实现的接口中方法======
    public FSM fsm
    {
        get;set;
    }

    public StateType stateType
    {
        get
        {
            return StateType.Follow;
        }
         
    }

    //状态进入,初始化
    public void EnterState()
    {

        targetObj = GameObject.FindGameObjectWithTag("Player");
        this.fsm.Role.GetComponent().SetBool("run", true);
        this.fsm.Role.GetComponent().Resume();
    }

    ///
    ///
    ///

    public void ExitState()
    {
        this.fsm.Role.GetComponent().SetBool("run", false);
    }

    public void StateUpdate(float deltaTime)
    {
        //向玩家移动
        this.fsm.Role.GetComponent().SetDestination(targetObj.transform.position);
        AnimatorStateInfo stateinfo = this.fsm.Role.GetComponent().GetCurrentAnimatorStateInfo(0);
        if(stateinfo.IsName("Run"))
        {
            this.fsm.Role.GetComponent().Resume();
        }
        else
        {
            this.fsm.Role.GetComponent().Stop();
        }

    }

    ///
    /// 做一些向其他状态切换的条件判断,及切换。
    ///

    ///
    public void StateLateUpdate(float deltaTime)
    {

        float dis = Vector3.Distance(this.fsm.Role.transform.position, targetObj.transform.position);
        if (dis < 1)
        {
            this.fsm.changeState(StateType.Attack);
        }
        else if (dis > 6)
        {
            this.fsm.changeState(StateType.Partrol);
        }
    }
}

 
 
**************************************************************************************************************************

using UnityEngine;
using UnityEngine.AI;

public class PartrolState : IState
{
    private GameObject targetObj;
    private Vector3 v;
    private float timeCount;
    public FSM fsm
    {
        get; set;
    }

    public StateType stateType
    {
        get { return StateType.Partrol; }
    }

    public void EnterState()
    {
        timeCount = 0;
        targetObj = GameObject.FindGameObjectWithTag("Player");
        this.fsm.Role.GetComponent().SetBool("run", true);

   
    }

    public void ExitState()
    {
        this.fsm.Role.GetComponent().SetBool("run", false);
    }

    public void StateLateUpdate(float deltaTime)
    {
        float dis = Vector3.Distance(this.fsm.Role.transform.position, targetObj.transform.position);
        if (dis < 6)
        {
            this.fsm.changeState(StateType.Follow);
        }
        else if (dis < 1)
        {
            this.fsm.changeState(StateType.Attack);
        }
    }

    public void StateUpdate(float deltaTime)
    {
        //随机走。
        if(timeCount>3)
        {
            timeCount = 0; //归零

            Vector2 vec = UnityEngine.Random.insideUnitCircle;

            Vector2 randomPos = vec * 2 + vec.normalized * 2;  //2---10米的随机向量

            v = this.fsm.Role.transform.position + new Vector3(randomPos.x, 0, randomPos.y);

            this.fsm.Role.GetComponent().SetDestination(v);
        }
        else
        {
            timeCount += deltaTime;
        }
    }
}



你可能感兴趣的:(unity)