Unity3D设计模式之命令者模式

发表于2018-07-12
评论0 1.7k浏览
设计模式分很多种,大家或多或少的都有些了解,但真的说到掌握,可能很多人都没什么信心,为此为了加深大家对设计模式的理解,下面就给大家介绍下设计模式中的命令者模式。

命令者模式的定义

“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二者之间的松耦合。这就是命令模式。

命令者模式的原理


命令者模式举例—>FSM状态机

首先分析:共同的特性
1.切换到另一种状态时都要先退出当前状态
2.进入要切换的状态
3.每一帧 处理当前的状态涉及的逻辑

接下来上代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//抽象出的父类
public abstract class FSMBase
{
    protected Animator animator;
    public FSMBase(Animator temAnimator)
    {
        animator = temAnimator;
    }
    //进入状态
    public abstract void OnEnter();
    //当前状态
    public abstract void Update();
    //离开状态
    public abstract void OnLeave();
}
//管理类
public class FSMManager
{
    /// <summary>
    /// 当前添加的状态数
    /// </summary>
    byte currentIndex;
    /// <summary>
    /// 当前的状态值  
    /// </summary>
    int currentState;
    //将所有的动画管理起来
    FSMBase[] allState;
    /// <summary>
    /// count当前动画的数量
    /// </summary>
    /// <param name="count"></param>
    public FSMManager(int count)
    {
        allState = new FSMBase[count];
        currentIndex = 0;
        currentState = -1;
    }   
    /// <summary>
    /// 将所有的状态添加到数组
    /// </summary>
    /// <param name="temBase"></param>
    public void AddState(FSMBase temBase)
    {
        if (currentIndex < allState.Length)
        {
            allState[currentIndex] = temBase;
            currentIndex++;
        }
    }
    /// <summary>
    /// 切换到某一个状态
    /// </summary>
    /// <param name="index"></param>
    public void ChangeState(byte index)
    {
        //判断当前状态是否等于要切换的状态
        if (currentState != index)
        {
            if (currentState != -1)
            {
                //退出当前状态
                allState[currentState].OnLeave();
            }
            //切换到目标状态
            allState[index].OnEnter();
            //记录当前状态
            currentState = index;
        }
    }
    public void Update()
    {
        if (currentState != -1)
        {
            allState[currentState].Update();
        }
    }
}
public class FSM : MonoBehaviour {
    // Use this for initialization
    void Start () {
    }
    // Update is called once per frame
    void Update () {
    }
}

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerIdle : FSMBase
{
    public PlayerIdle(Animator temAnimator) : base(temAnimator)
    {
    }
    public override void OnEnter()
    {
        animator.SetInteger("StateIndex", 0);
    }
    public override void OnLeave()
    {
    }
    public override void Update()
    {
    }
}
public class PlayerWalk : FSMBase
{
    public PlayerWalk(Animator temAnimator) : base(temAnimator)
    {
    }
    public override void OnEnter()
    {
        animator.SetInteger("StateIndex", 1);
    }
    public override void OnLeave()
    {
    }
    public override void Update()
    {
    }
}
public class PlayerRun : FSMBase
{
    public PlayerRun(Animator temAnimator) : base(temAnimator)
    {
    }
    public override void OnEnter()
    {
        animator.SetInteger("StateIndex", 2);
    }
    public override void OnLeave()
    {
    }
    public override void Update()
    {
    }
}
public class PlayerAttack : FSMBase
{
    public PlayerAttack(Animator temAnimator) : base(temAnimator)
    {
    }
    public override void OnEnter()
    {
        animator.SetInteger("StateIndex", 3);
    }
    public override void OnLeave()
    {
    }
    public override void Update()
    {
    }
}
public class PlayerAnimation0 : MonoBehaviour {
    FSMManager animatorManager;
    public enum AnimatorState
    {
        Idle,
        Walk,
        Run,
        Attack,
        MaxValue
    }
    // Use this for initialization
    void Start () {
        animatorManager = new FSMManager((int)AnimatorState.MaxValue);
        Animator ani = gameObject.GetComponent<Animator>(); 
        PlayerIdle idle = new PlayerIdle(ani);
        animatorManager.AddState(idle);
        PlayerWalk walk = new PlayerWalk(ani);
        animatorManager.AddState(walk);
        PlayerRun run = new PlayerRun(ani);
        animatorManager.AddState(run);
        PlayerAttack attack = new PlayerAttack(ani);
        animatorManager.AddState(attack);
    }
    // Update is called once per frame
    void Update () {
        if (Input.GetKeyDown(KeyCode.A))
        {
            ChangeState((int)AnimatorState.Attack);
        }
    }
    public void ChangeState(byte index)
    {
        animatorManager.ChangeState(index);
    }
}
优点
1.两个状态之间的耦合性比较低
2.可扩展性比较强
来自:https://blog.csdn.net/battletiger/article/details/78020310

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引