Unity3D 设计模式---命令者模式

来源:互联网 发布:除法公式有几种算法 编辑:程序博客网 时间:2024/06/15 04:22

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

命令者模式的原理
这里写图片描述

命令者模式举例—>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.可扩展性比较强