Unity实现设计模式——命令模式

Unity实现设计模式------命令模式

推荐一个Unity学习设计模式很好的GitHub地址:https://github.com/QianMo/Unity-Design-Pattern 有非常多的Star

一、介绍

命令模式使得请求的发送者与请求的执行者之间消除耦合,让对象之间的调用关系更加灵活。在命令模式中,会将一个命令封装成一个对象,同时命令模式也支持可撤销的操作。

命令里面通常聚合接收者,初始化命令时传入接收者,调用者直接调用命令即可

二、实现

这里使用Unity上下左右控制物体移动同时记录移动信息方便撤回为例子演示命令模式

1.ICommand

命令接口基类

csharp 复制代码
public interface ICommand
{
    void Execute();
    void UnExecute();
}

2.MoveCommand

具体的移动命令

csharp 复制代码
class MoveCommand : ICommand
{
    private MoveDirection _direction;
    private MoveCommandReceiver _receiver;
    private float _distance;
    private GameObject _gameObject;


    //Constructor
    public MoveCommand(MoveCommandReceiver reciever, MoveDirection direction, float distance,
        GameObject gameObjectToMove)
    {
        this._receiver = reciever;
        this._direction = direction;
        this._distance = distance;
        this._gameObject = gameObjectToMove;
    }


    //Execute new command
    public void Execute()
    {
        _receiver.MoveOperation(_gameObject, _direction, _distance);
    }


    //Undo last command
    public void UnExecute()
    {
        _receiver.MoveOperation(_gameObject, InverseDirection(_direction), _distance);
    }


    //invert the direction for undo
    private MoveDirection InverseDirection(MoveDirection direction)
    {
        switch (direction)
        {
            case MoveDirection.up:
                return MoveDirection.down;
            case MoveDirection.down:
                return MoveDirection.up;
            case MoveDirection.left:
                return MoveDirection.right;
            case MoveDirection.right:
                return MoveDirection.left;
            default:
                Debug.LogError("Unknown MoveDirection");
                return MoveDirection.up;
        }
    }


    //So we can show this command in debug output easily
    public override string ToString()
    {
        return _gameObject.name + " : " + MoveDirectionString(_direction) + " : " + _distance.ToString();
    }


    //Convert the MoveDirection enum to a string for debug
    public string MoveDirectionString(MoveDirection direction)
    {
        switch (direction)
        {
            case MoveDirection.up:
                return "up";
            case MoveDirection.down:
                return "down";
            case MoveDirection.left:
                return "left";
            case MoveDirection.right:
                return "right";
            default:
                return "unkown";
        }
    }
}

3.MoveCommandReceiver

命令接收者

csharp 复制代码
class MoveCommandReceiver
    {
        public void MoveOperation(GameObject gameObjectToMove, MoveDirection direction, float distance)
        {
            switch (direction)
            {
                case MoveDirection.up:
                    MoveY(gameObjectToMove, distance);
                    break;
                case MoveDirection.down:
                    MoveY(gameObjectToMove, -distance);
                    break;
                case MoveDirection.left:
                    MoveX(gameObjectToMove, -distance);
                    break;
                case MoveDirection.right:
                    MoveX(gameObjectToMove, distance);
                    break;
            }
        }

        private void MoveY(GameObject gameObjectToMove, float distance)
        {
            Vector3 newPos = gameObjectToMove.transform.position;
            newPos.y += distance;
            gameObjectToMove.transform.position = newPos;
        }

        private void MoveX(GameObject gameObjectToMove, float distance)
        {
            Vector3 newPos = gameObjectToMove.transform.position;
            newPos.x += distance;
            gameObjectToMove.transform.position = newPos;
        }
    }

4.命令的发出者(或者说是图中Clinet)

这里将命令发出者和Client放到了一起

csharp 复制代码
public class InputHandler : MonoBehaviour
{
    public float moveDistance = 10f;
    public GameObject objectToMove;

    private MoveCommandReceiver moveCommandReciever;
    private Stack<MoveCommand> commandStack1 = new Stack<MoveCommand>();
    private Stack<MoveCommand> commandStack2 = new Stack<MoveCommand>();

    void Start()
    {
        moveCommandReciever = new MoveCommandReceiver();

        if (objectToMove == null)
        {
            Debug.LogError("objectToMove must be assigned via inspector");
            this.enabled = false;
        }
    }


    public void Undo()
    {
        if (commandStack1.Count > 0)
        {
            MoveCommand moveCommand = commandStack1.Pop();
            moveCommand.UnExecute();
            commandStack2.Push(moveCommand);
        }
    }

    public void Redo()
    {
        if (commandStack2.Count > 0)
        {
            MoveCommand moveCommand = commandStack2.Pop();
            moveCommand.Execute();
            commandStack1.Push(moveCommand);
        }
    }

    private void Move(MoveDirection direction)
    {
        MoveCommand moveCommand = new MoveCommand(moveCommandReciever, direction, moveDistance, objectToMove);
        moveCommand.Execute();
        commandStack1.Push(moveCommand);
    }


    //Simple move commands to attach to UI buttons
    public void MoveUp() { Move(MoveDirection.up); }
    public void MoveDown() { Move(MoveDirection.down); }
    public void MoveLeft() { Move(MoveDirection.left); }
    public void MoveRight() { Move(MoveDirection.right); }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            MoveUp();
        }
        if (Input.GetKeyDown(KeyCode.DownArrow))
        {
            MoveDown();
        }
        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            MoveLeft();
        }
        if (Input.GetKeyDown(KeyCode.RightArrow))
        {
            MoveRight();
        }
        if (Input.GetKeyDown(KeyCode.R))
        {
            Redo();
        }
        if (Input.GetKeyDown(KeyCode.U))
        {
            Undo();
        }
    }
}
相关推荐
异次元的归来4 小时前
Unity DOTS中的share component
unity·游戏引擎
向宇it7 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
_oP_i8 小时前
unity webgl部署到iis报错
unity
Go_Accepted8 小时前
Unity全局雾效
unity
向宇it8 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
思忖小下10 小时前
梳理你的思路(从OOP到架构设计)_简介设计模式
设计模式·架构·eit
每日出拳老爷子11 小时前
【图形渲染】【Unity Shader】【Nvidia CG】有用的参考资料链接
unity·游戏引擎·图形渲染
liyinuo201712 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
北海651612 小时前
Dots 常用操作
unity
aaasssdddd9614 小时前
C++的封装(十四):《设计模式》这本书
数据结构·c++·设计模式