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

news2024/12/28 23:20:28

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

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

一、介绍

命令模式使得请求的发送者与请求的执行者之间消除耦合,让对象之间的调用关系更加灵活。在命令模式中,会将一个命令封装成一个对象,同时命令模式也支持可撤销的操作。
在这里插入图片描述
命令里面通常聚合接收者,初始化命令时传入接收者,调用者直接调用命令即可

二、实现

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

1.ICommand

命令接口基类

public interface ICommand
{
    void Execute();
    void UnExecute();
}

2.MoveCommand

具体的移动命令

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

命令接收者

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放到了一起

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();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1044130.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

聊聊零拷贝技术原理和应用

文章目录 0. 引言1. 什么是零拷贝技术 1. 零拷贝技术在不同领域的应用2.传统拷贝技术的缺点3. 零拷贝技术的原理与实现1. sendfile系统调用2. 内核缓冲区与用户缓冲区3. DMA&#xff08;Direct Memory Access&#xff09;技术4. 文件描述符传递与共享5. Direct I/O&#xff08;…

Apache shiro RegExPatternMatcher 权限绕过漏洞 (CVE-2022-32532)

漏洞描述 2022年6月29日&#xff0c;Apache 官方披露 Apache Shiro &#xff08;CVE-2022-32532&#xff09;权限绕过漏洞。 当Apache Shiro中使用RegexRequestMatcher进行权限配置&#xff0c;且正则表达式中携带"."时&#xff0c;未经授权的远程攻击者可通过构造恶…

基于Springboot实现毕业生信息招聘平台管理系统演示【项目源码+论文说明】分享

基于Springboot实现毕业生信息招聘平台管理系统演示 摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 毕业生信息招聘平台&#xff0c;主要的模块包括查看管理员&#xff1b;首页、个人中心、企…

Nginx 可视化管理工具与 cpolar 配置:实现远程访问本地服务的优化

文章目录 前言1. docker 一键安装2. 本地访问3. Linux 安装cpolar4. 配置公网访问地址5. 公网远程访问6. 固定公网地址 前言 Nginx Proxy Manager 是一个开源的反向代理工具&#xff0c;不需要了解太多 Nginx 或 Letsencrypt 的相关知识&#xff0c;即可快速将你的服务暴露到外…

服务断路器_服务雪崩解决方案之服务降级

什么是服务降级 两种场景: 当下游的服务因为某种原因响应过慢&#xff0c;下游服务主动停掉一些不太重要的业务&#xff0c;释放出服务器资源&#xff0c;增加响应速度&#xff01;当下游的服务因为某种原因不可用&#xff0c;上游主动调用本地的一些降级逻辑&#xff0c;避免…

SPA移动端解决方案参考

企业在实现SAP移动化时遇到的一些挑战&#xff0c;如果我们利用自己开发团队来进行应用程序的开发&#xff0c;可能会陷入规划&#xff0c;开发&#xff0c;调试&#xff0c;测试的循环中&#xff0c;最后仍一无所获。那如果企业寻找第三方咨询公司进行开发的话&#xff0c;又担…

【高阶数据结构】哈希的应用 {位图;std::bitset;位图的应用;布隆过滤器;布隆过滤器的应用}

一、位图 1.1 位图概念 面试题 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中。【腾讯】 遍历查找&#xff1a;内存中无法存放40亿个整数&#xff08;约占内存15-16G&#xff09;&#xff1b;时间复杂…

项目经理工具箱

新项目经理误区 要解决的关键点 事&#xff1a;范围&#xff0c;进度&#xff0c;成本&#xff0c;质量 人&#xff1a;项目干系人&#xff0c;团队&#xff0c;外包成员&#xff1b; 干系人管理计划&#xff0c;沟通管理计划 技术和管理区别和联系 非暴力沟通 结构思考力 重…

正点原子lwIP学习笔记——NTP实时时间实验

1. NTP简介 NTP&#xff08;Network Time Protocol&#xff09;网络时间协议基于UDP&#xff0c;用于网络时间同步的协议&#xff0c;使网 络中的计算机时钟同步到UTC&#xff0c;再配合各个时区的偏移调整就能实现精准同步对时功能。 NTP 服务器&#xff08;Network Time Pr…

ERROR in docs.42140ac.js from UglifyJs webpack打包报错

ERROR in docs.42140ac.js from UglifyJs 原因是UglifyJs 针对js压缩 不支持es6语法&#xff08;或者引入的第三方插件存在es6语法&#xff09; ERROR in docs.42140ac.js from UglifyJs 使用的 uglifyjs-webpack-plugin 解决方法 降低uglifyjs-webpack-plugin的版本 “ugl…

系统化思考,从初级到高级书单推荐

用思考工具进行系统思考&#xff0c;解决复杂问题&#xff0c;成为某个领域的高手&#xff0c;下面这几本书就是补充你脑海的系统思考的工具&#xff0c;一定要保存。 《简单的逻辑学》 作者&#xff1a;麦克伦尼 一切的系统源自于逻辑&#xff0c;如果你没有逻辑分析的能力&…

[谷粒商城笔记]07、Linux环境-虚拟机网络设置

1.本机cmd,输入命令ipconfig,查看本地ip 192.168.56.1是虚拟机的ip 2.自定义虚拟机ip 修改这个文件下的 这里&#xff0c;把ip换成 192.168.56.‘10’ 引号内数字自定义 3.在本机和虚拟机命令行&#xff0c;互相ping IP 查看是否设置成功

静态NAT,动态NAT,NAPT(实验配置+原理讲解)

目录 静态NAT,动态NAT&#xff0c;NAPT 实验一&#xff1a;静态NAT地址转换 实验二&#xff1a;动态NAT配置 实验三&#xff1a;NAPT配置 静态NAT,动态NAT&#xff0c;NAPT 静态地址转换&#xff1a;只能实现一个私网与一个公网的一对一映射 动态地址转换&#xff1a;创建…

Python 编程基础 | 第一章-预备知识 | 1.5、开发工具

一、开发工具 - VSCode VSCode是一个相当优秀的IDE&#xff0c;具备开源、跨平台、模块化、插件丰富、轻量化、启动时间快、颜值高的特质。 1、下载VSCode VSCode下载地址&#xff1a;https://code.visualstudio.com/ 2、安装VSCode 载软件包&#xff0c;一步步安装即可&#x…

CSS笔记——基本语法及相关知识

CSS层叠样式表是用于定义 HTML 或 XML 文档的样式和布局的语言。它可以让开发者更加灵活地控制页面元素的样式和排版&#xff0c;从而提高页面的可读性和用户体验 一、css样式书写顺序和规范 CSS样式的书写顺序和规范是为了让代码更易读、易维护和易扩展。下面是一些常见的规…

嵌入式Linux应用开发-Makefile 的使用

嵌入式Linux应用开发-Makefile 的使用 第三章 Makefile 的使用3.1 配套视频内容大纲3.1.1 Makefile 规则与示例3.1.2 通用 Makefile 的使用3.1.3 通用 Makefile 的解析 3.2 Makefile 规则3.3 Makefile 文件里的赋值方法3.4.1 字符串替换和分析函数3.4.2 文件名函数3.4.3 其他函…

NeRF中的位置编码

朴素NeRF中直接采用频率变换来做位置编码&#xff0c;为的是避免空间相邻采样点在MLP表示中的过平滑问题。比如位置(237, 332, 198)和位置(237,332,199)这两个点作为MLP的输入&#xff0c;MLP可能对个位不够敏感&#xff0c;导致输出过平滑的问题。例如&#xff1a; 由于缺乏位…

华为云云耀云服务器L实例评测 | 实例使用教学之软件安装:华为云云耀云服务器环境下安装 Docker

华为云云耀云服务器L实例评测 &#xff5c; 实例使用教学之软件安装&#xff1a;华为云云耀云服务器环境下安装 Docker 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为云云耀云…

特种设备安全监测终端,降低安全隐患风险!

特种设备运行关系到人民生命财产安全&#xff0c;关系到经济健康发展&#xff0c;关系到社会的稳定。有关特种设备的事故基本都发生在使用过程中&#xff0c;因此&#xff0c;使用过程的安全管理是特种设备的管理重点。针对国内特种设备本身存在事故隐患及安装、维修、操作、指…

基于微信小程序的快递配送管理平台系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…