游戏中的设计模式之命令模式 笔记

源代码来自:https://github.com/TYJia/GameDesignPattern_U3D_Version

命令模式基本思想:将命令封装,与目标行为解耦,使命令由流程概念变为对象数据(需要大量实例化命令对象)

缺点:可能会导致大量的实例化,从而浪费内存

扩展:可用享元模式代替大量的实例化

命令变成了数据,也就变成了可被传递、存储、重复利用的:

  • 通过命令数据 队列/栈 可以轻易实现撤销、重做、时光倒流
  • 命令数据还可以形成日志,用于复现用户行为,便于重复测试同样序列命令对各种目标的影响
  • 这些命令数据可以发送给不同的目标,比如同样的“出发,5分钟后,停止”,发送给飞机就可以变成“起飞,5分钟后,降落”,发送给轮船就成了“离港,5分钟后,抛锚”

Command.cs

//抽象基类,包含了时间戳和运行、回退的虚方法
public abstract class Command {

    protected float _TheTime;
    public float TheTime
    {
        get { return _TheTime; }
    }
    public virtual void execute(Avatar avatar) { }
    public virtual void undo(Avatar avatar) { }
}

CommandMove.cs

using UnityEngine;

//Command的子类,可以调用指定Avatar的Move函数
public class CommandMove : Command {

    private Vector3 TransPos;

    public CommandMove(Vector3 transPos, float time)
    {
        TransPos = transPos;
        _TheTime = time;
    }
    public override void execute(Avatar avatar)
    {
        avatar.Move(TransPos);
    }
    public override void undo(Avatar avatar)
    {
        avatar.Move(-TransPos);
    }
}

CommandManager.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/*
    当IsRun为true时,由WASD按键生成命令对象,执行Execute(Avatar)
    当IsRun为false时,调用RunCallBack(),按时间将栈内命令提取出并执行Undo(Avatar)
 */
public class CommandManager : MonoBehaviour
{

    public Avatar TheAvatar;

    private Stack<Command> mCommandStack;
    private float mCallBackTime;
    public bool IsRun = true;

    // Use this for initialization
    void Start()
    {
        mCommandStack = new Stack<Command>();
        mCallBackTime = 0;
    }

    // Update is called once per frame
    void Update()
    {
        if (IsRun)
        {
            Control();
        }
        else
        {
            RunCallBack();
        }

    }

    private void RunCallBack()
    {
        mCallBackTime -= Time.deltaTime;
        if (mCommandStack.Count > 0 && mCallBackTime < mCommandStack.Peek().TheTime) //Peek返回栈顶值,不删除
        {
            mCommandStack.Pop().undo(TheAvatar);
        }
    }

    private Command InputHandler()
    {
        if (Input.GetKey(KeyCode.W))
        {
            return new CommandMove(new Vector3(0, Time.deltaTime, 0), mCallBackTime);
        }
        if (Input.GetKey(KeyCode.S))
        {
            return new CommandMove(new Vector3(0, -Time.deltaTime, 0), mCallBackTime);
        }
        if (Input.GetKey(KeyCode.A))
        {
            return new CommandMove(new Vector3(-Time.deltaTime, 0, 0), mCallBackTime);
        }
        if (Input.GetKey(KeyCode.D))
        {
            return new CommandMove(new Vector3(Time.deltaTime, 0, 0), mCallBackTime);
        }
        return null;
    }

    private void Control()
    {
        mCallBackTime += Time.deltaTime;
        Command cmd = InputHandler();
        if (cmd != null)
        {
            mCommandStack.Push(cmd);
            cmd.execute(TheAvatar);
        }
    }
}

 

Avatar.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//执行行为的目标物体,拥有Move函数
public class Avatar : MonoBehaviour {

    private Transform mTransform;

	void Start () {
        mTransform = transform;
	}

    public void Move(Vector3 DeltaV3)
    {
        mTransform.Translate(DeltaV3);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值