Unity进阶第三章-有限状态机FSM(三种方法实现角色动画操作)

一、有限状态机FSM概述

在这里插入图片描述

二、不用有限状态机实现角色的走路、攻击动作

(1)新建角色、地面、为角色添加动画
在这里插入图片描述
在这里插入图片描述
(2)为角色添加脚本

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

public class Player1Control : MonoBehaviour
{
    
    
    private Animator ani;
    void Start()
    {
    
    
        ani = GetComponent<Animator>();   
    }

    // Update is called once per frame
    void Update()
    {
    
    
        float vertical = Input.GetAxis("Vertical");
        float horizontal = Input.GetAxis("Horizontal");
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        if (dir != Vector3.zero)
        {
    
    
            transform.rotation = Quaternion.LookRotation(dir);
            transform.Translate(Vector3.forward * 3 * Time.deltaTime);
            ani.SetBool("IsWalk", true);
        }
        else
        {
    
    
            ani.SetBool("IsWalk", false);
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
    
    
            ani.SetTrigger("Attack");
        }
        
    }
}

这样是能够实现角色的各种动画,但是由于if语句过多,可能以后修改起来会很麻烦。

三、用方法实现角色的走路、攻击动作

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

public enum PlayerState
{
    
    
    idle,
    walk,
    attack
}
public class Player2Control2 : MonoBehaviour
{
    
    
    private Animator ani;
    private PlayerState state = PlayerState.idle;
    // Start is called before the first frame update
    void Start()
    {
    
    
        ani = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
    
    
        switch (state)
        {
    
    
            case PlayerState.idle:
                idle();
                break;
            case PlayerState.walk:
                walk();
                break;
            case PlayerState.attack:
                attack();
                break;

        }
    }
    void idle()
    {
    
    
        //站立方法
        ani.SetBool("IsWalk", false);
        float vertical = Input.GetAxis("Vertical");
        float horizontal = Input.GetAxis("Horizontal");
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        if (dir != Vector3.zero)
        {
    
    
            //切换为走路状态
            state = PlayerState.walk;
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
    
    
            //切换为攻击状态
            state = PlayerState.attack;
        }
    }
    void walk()
    {
    
    
        ani.SetBool("IsWalk", true);
        float vertical = Input.GetAxis("Vertical");
        float horizontal = Input.GetAxis("Horizontal");
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        if (dir != Vector3.zero)
        {
    
    
            transform.rotation = Quaternion.LookRotation(dir);
            transform.Translate(Vector3.forward * 3 * Time.deltaTime);
        }
        else
        {
    
    
            state = PlayerState.idle;
        }
    }
    void attack()
    {
    
    
        ani.SetTrigger("Attack");
        //如果你当前的状态不是攻击,切换状态
        if (!ani.GetCurrentAnimatorStateInfo(0).IsName("Elemental@UnarmedAttack01")) ;
        {
    
    
            state = PlayerState.idle;
        }
    }
}

三、用类实现角色的走路、攻击动作

在这里插入图片描述

状态类

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

public enum PlayerState
{
    
    
    idle,
    walk,
    attack
}
public abstract class FSMstate 
{
    
    
    //当前状态ID
    public int StateID;
    //当前状态拥有者
    public MonoBehaviour mono;
    //状态所属管理器
    public FSMManager fSMManager;
    public FSMstate(int StateID,MonoBehaviour mono,FSMManager manager)
    {
    
    
        this.StateID = StateID;
        this.mono = mono;
        this.fSMManager = manager;
    }
    public abstract void OnEnter();
    public abstract void OnUpdate();
}

状态管理类

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

public class FSMManager : MonoBehaviour
{
    
    
    // Start is called before the first frame update
    //列表状态
    public List<FSMstate> stateList = new List<FSMstate>();
    //当前状态
    public int CurrentIndex = -1;
    public void ChangeState(int StateID)
    {
    
    
        stateList[CurrentIndex].OnEnter();
        CurrentIndex = StateID;
    }
    //更新
    public void Update()
    {
    
    
        if (CurrentIndex != -1)
        {
    
    
            stateList[CurrentIndex].OnUpdate();
        }
    }
}

PlayerControl类

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

public class Payer : MonoBehaviour
{
    
    
    private FSMManager fSMManager;
    void Start()
    {
    
    
        fSMManager = new FSMManager();
        IdleState idle = new IdleState(0,this,fSMManager);
        WalkState walk = new WalkState(1, this, fSMManager);
        AttackState attack = new AttackState(2, this, fSMManager);
        fSMManager.stateList.Add(idle);
        fSMManager.stateList.Add(walk);
        fSMManager.stateList.Add(attack);
        fSMManager.ChangeState((int)PlayerState.idle);
    }
    void Update()
    {
    
    
        fSMManager.Update();
    }
}

IdleState类

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

public class IdleState : FSMState
{
    
    
    public IdleState(int stateID,MonoBehaviour mono,FSMManager manager) : base(stateID, mono, manager)
    {
    
    

    }
    public override void OnEnter()
    {
    
    
        mono.GetComponent<Animator>().SetBool("IsWalk", false);
    }

    public override void OnUpdate()
    {
    
    
        float vertical = Input.GetAxis("Vertical");
        float horizontal = Input.GetAxis("Horizontal");
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        if (dir != Vector3.zero)
        {
    
    
            fSMManager.ChangeState((int)PlayerState.walk);
        }
        //监听攻击状态切换
        if (Input.GetKeyDown(KeyCode.Space))
        {
    
    
            fSMManager.ChangeState((int)PlayerState.attack);
        }
    }


}

WalkState类

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

public class WalkState : FSMState
{
    
    
    public WalkState(int stateID,MonoBehaviour mono,FSMManager manager) : base(stateID, mono, manager)
    {
    
    

    }
    public override void OnEnter()
    {
    
    
        mono.GetComponent<Animator>().SetBool("IsWalk", true);
    }

    public override void OnUpdate()
    {
    
    
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        if (dir != Vector3.zero)
        {
    
    
            mono.transform.rotation = Quaternion.LookRotation(dir);
            mono.transform.Translate(Vector3.forward * 3 * Time.deltaTime);
        }
        else
        {
    
    
            //切换到站立状态
            fSMManager.ChangeState((int)PlayerState.idle);
        }
    }

    // Start is called before the first frame update
    
}

AttackState类

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

public class AttackState : FSMState
{
    
    
   public AttackState(int stateID,MonoBehaviour mono,FSMManager manager) : base(stateID, mono, manager)
    {
    
    

    }

    public override void OnEnter()
    {
    
    
        mono.GetComponent<Animator>().SetTrigger("Attack");
    }

    public override void OnUpdate()
    {
    
    
        if (!mono.GetComponent<Animator>().GetCurrentAnimatorStateInfo(0).IsName("Elemental@UnarmedAttack01"))
        {
    
    
            fSMManager.ChangeState((int)PlayerState.idle);
        }
        
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43853077/article/details/125913774
今日推荐