Unity Finite State Machine (FSM)

The finite state machine can provide a simple AI system for the enemy, which allows us to manually write each state individually and play animations for it, but the player that needs to be controlled by the player is not suitable for the finite state machine, the player's input Event is too complicated

Write an IState interface, let all states implement these three interfaces,

接口中定义三个抽象函数,分别是:
OnEnter() :在每次进入该状态时会调用一次, 
OnExecute() : 每帧执行一次
OnExit(): 退出状态时执行一次
public interface IState{
    
    
	void onEnter();
	void OnExecute();
	void OnExit();
}

Improve the finite state machine script

1.定义枚举类型的所需状态
2.定义我们所需要的类,并且时期能够被序列化[Serliazeable]
using System; //使用[Serializable]所需要的命名空间
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum StateType{
    
    
	Idle, Attack, Patrol
}

[Serializable]
public class Parameter{
    
    
	public float idleTime;
	public Animation animator;
	public Transform target;
}

public class FSM : MonoBevirour{
    
    
	
	public Parameter parameter;
	public IState currentState ;
	private Dictionary<StateType, IState> dict = new Dictionart<StateType, IState>();
	void Start(){
    
    
		dict.Add(StateType.Idle, new IdleState(this));
        dict.Add(StateType.Attack, new AttackState(this));
        dict.Add(StateType.Patrol, new PatrolState(this));
		TransitionState(StateType.Idle);

	}
	
	//物理运动建议使用FixedUpdate 函数来更新
	void FixedUpdate(){
    
    
		currentState.OnExecute();
	}
	
	//提供一个公共函数来转换状态
	void TransitionState(StateType targetState){
    
    
		if(currentState != null){
    
    
			currentState.OnExit();
		}
		currentState = dict[targetState];
		currentState.OnEnter();
	}
}

Next, let the concrete state class inherit the interface and implement the abstract function

可以把所有的具体状态放在一个文件中修改
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class IdleState : IState{
    
    
	
	private FSM manager;
    private Parameter parameter;
    private float timer = 0;
    public IdleState(FSM manager)
    {
    
    
        this.manager = manager;
        this.parameter = manager.parameter;
    }

    public void OnEnter()
    {
    
    
        parameter.animator.SetTrigger("idle");
    }

    public void OnExecute()
    {
    
       
        // parameter.animator.SetTrigger("idle");
        timer += Time.deltaTime;

        if(timer > parameter.idleTime){
    
    
            manager.TransitionState(StateType.Patrol);
        }
        
        if(parameter.target)
        {
    
       
            manager.TransitionState(StateType.Attack);
        }
    }

    public void OnExit()
    {
    
    
        timer = 0;
    }
	
}

//巡逻
public class PatrolState : IState
{
    
    
    private FSM manager;

    private Parameter parameter;

    private int patrolPosition = 0;
    public PatrolState(FSM manager)
    {
    
    
        this.manager = manager;
        this.parameter = manager.parameter;
    }


    public void OnEnter()
    {
    
    
        parameter.animator.SetBool("isRun",true);
    }

    public void OnExecute()
    {
    
       
        //如果发现了玩家,并追击范围
        //note : 应该主动撤销target的方式来节俭判定
        if(parameter.target)
        {
    
       
            manager.TransitionState(StateType.Chase);
        }

        //使敌人持续朝向下一个巡逻点
        manager.FlipTo(parameter.patrolPoints[patrolPosition]);
        
        // Debug.Log("Patrol" + parameter.animator.GetBool("isRun"));

        manager.transform.position = Vector2.MoveTowards(manager.transform.position, 
            parameter.patrolPoints[patrolPosition].position, parameter.moveSpeed * Time.deltaTime);
        
        //向量类中有直接计算距离的函数真是太棒了
        if(Vector2.Distance(manager.transform.position, parameter.patrolPoints[patrolPosition].position ) < 0.1f)
        {
    
    
            manager.TransitionState(StateType.Idle);
        }
    }

    public void OnExit()
    {
    
    
        parameter.animator.SetBool("isRun",false);

        patrolPosition ++;
        if(patrolPosition >= parameter.patrolPoints.Length){
    
    
            patrolPosition = 0;
        }
    }
}


//攻击
public  class AttackState : IState {
    
    
	private FSM manager;

    private Parameter parameter;

    private AnimatorStateInfo info;

    public AttackState(FSM manager){
    
    
        this.manager = manager;
        this.parameter = manager.parameter;
    }

    public void OnEnter()
    {
    
    
        parameter.animator.Play("Attack");
    }

    public void OnExecute()
    {
    
       
        //得到动画器的播放状态
        info = parameter.animator.GetCurrentAnimatorStateInfo(0);
        if(info.normalizedTime > .95f){
    
    
            manager.TransitionState(StateType.Chase);
        }
    }

    public void OnExit()
    {
    
       

    }
} 


代码仅提供思路,由于是默写的,不能确保没有错误

Guess you like

Origin blog.csdn.net/blastospore/article/details/130580078