Unity设计模式—命令模式(附代码)

Unity设计模式—命令模式(附代码)

命令模式是什么

命令模式是回调函数的面向对象替代品。它将一个请求封装成一个对象,从而让你可以用不同的请求对客户进行参数化,对请求排队或者记录请求日志以支持可以撤销的操作。

具体不展开,本篇主旨是在Unity中实现与演示命令模式,有关命令模式的详细介绍可以看Refactoring.Guru,肯定比我讲得好。

什么时候用

  • 如果你需要通过操作来参数化对象, 可使用命令模式。
  • 如果你想要将操作放入队列中、 操作的执行或者远程执行操作, 可使用命令模式。
  • 如果你想要实现操作回滚功能, 可使用命令模式。

如:

  • 制作Replay系统
  • 建立撤销和重做系统
  • AI命令流
  • 一组操作组合成宏命令

命令模式优缺点

优点

  • 把请求发送者和请求接收者进行了解耦,发送者和接收者之间不交互。
  • 可以方便的设计命令队列或组合命令。
  • 为Undo和Redo提供了一种设计与实现。

缺点

  • 具体命令类有点多,如果没有编辑器和语言的强力支持(如你是用Lua开发),引入命令模式维护成本比较高

结构

命令模式包含一个抽象命令类,具体命令类,调用者,和接收者这四个角色。

Unity中实现

需求

玩家通过键盘操作对象。

  • 按上箭头放大对象,按下箭头缩小对象
  • 按左箭头向左旋转90度,按右箭头向右旋转90度
  • WASD控制前左后右移动
  • 回车回放
    (先想一想如果不用设计模式,你的代码会怎么写)

实现

抽象命令类Command.cs声明了Execute()和Undo():

// 命令模式抽象类
// 这个类应该一直保持这个结构,保持足够通用,不应该引入构造函数,变量
public abstract class Command
{
    public abstract void Execute();

    public abstract void Undo();
}

具体命令类继承Command类,会存在很多个具体命令类,这里举例LargerCommand.cs用于放大操作对象:

public class LargerCommand : AbstractCommand
{
    // 维持一个对操作对象的引用
    public Transform transform;
    public LargerCommand(Transform transform)
    {
        this.transform = transform;
    }
    public override void Execute()
    {
        this.transform.localScale = this.transform.localScale * 2;
    }

    public override void Undo()
    {
        this.transform.localScale = this.transform.localScale / 2;
    }
}

调用者通过命令来操作接受者,实现调用者和接受者的解耦:

// 命令的指针执行XX动作
// 这一句调用是命令模式的精髓——把调用方和接收者进行了解耦
// 如果不用命令模式,这里的代码应该是直接调用接收者的方法,调用方的代码将会很庞大
var cmd = HandleInput();
if (cmd != null)
{
    cmd.Execute();
}

以上是基础结构。

维护一个undo栈和一个redo栈即可实现回放:

Command nextCommand = redoCommands.Pop();
nextCommand.Execute();
// 插入undo栈
undoCommands.Push(nextCommand);

可以将多个命令组合成一个命令组,参见:CommandQueue.cs

public class CommandQueue : AbstractCommand
{
    private List<AbstractCommand> _commands = new List<AbstractCommand>();


    /// <summary>
    /// 添加命令到队列中
    /// </summary>
    /// <param name="command"></param>
    public void AddCommand(AbstractCommand command)
    {
        _commands.Add(command);
    }

    /// <summary>
    /// 从队列中移除命令
    /// </summary>
    /// <param name="command"></param>
    public void RmCommand(AbstractCommand command)
    {
        _commands.Remove(command);
    }
    /// <summary>
    /// 执行
    /// </summary>
    public override void Execute()
    {
        foreach (AbstractCommand cmd in _commands)
        {
            cmd.Execute();
        }
    }
    /// <summary>
    /// 撤销
    /// </summary>
    public override void Undo()
    {
        foreach (AbstractCommand cmd in _commands)
        {
            cmd.Undo();
        }
    }
}

其他设计模式

专题 | Unity3D游戏开发中的设计模式 | 问渠 (wenqu.site)

源代码

完整代码已上传至nickpansh/Unity-Design-Pattern | GitHub

参考

Habrador/Unity-Programming-Patterns: A collection of open source programming patterns in Unity with examples when to use them (github.com)

Game Programming Patterns

Refactoring.Guru

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Unity 中常用的设计模式包括以下几种: 1. 单例模式(Singleton Pattern):用于确保一个类只有一个实例,并提供全局访问点。在 Unity 中,可以使用静态变量或者脚本组件的方式实现单例模式。 2. 观察者模式(Observer Pattern):用于实现对象间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都会得到通知并自动更新。在 Unity 中,可以使用事件系统或者委托实现观察者模式。 3. 工厂模式(Factory Pattern):用于封装对象的创建过程,隐藏具体类的实例化逻辑。在 Unity 中,可以通过工厂类或者抽象工厂来创建游戏对象或其他资源。 4. 命令模式(Command Pattern):用于将请求封装成一个对象,从而可以将请求的发送者和接收者解耦。在 Unity 中,可以通过委托或者事件来实现命令模式。 5. 组合模式(Composite Pattern):用于将对象组织成树形结构,并且可以以相同的方式处理单个对象和组合对象。在 Unity 中,可以使用游戏对象的层级结构来实现组合模式。 6. 状态模式(State Pattern):用于封装对象内部状态的变化,并根据状态的变化来改变对象的行为。在 Unity 中,可以使用状态机或者策略模式来实现状态模式。 这些设计模式可以帮助开发者更好地组织和管理 Unity 项目中的代码,提高代码的可维护性和可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NickPansh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值