游戏编程设计模式-命令模式Unity示例

在游戏编程里面,有一个经常会被用到的设计模式-命令模式。

我对设计模式的理解是

1、为解决问题而生。

2、有大致流程,但是没有固定格式

3、为了沟通方便。


在游戏编程里面,或者软件开发里面,最能体现命令模式的应用场景是

"撤销"与"再做"

在策略游戏里面,有时候我们会提供给玩家去模拟下一步的功能,在他还没确定之前都是能够撤销我们的行为的。比如象棋,比如五子棋,或者在商店系统的时候,玩家购买完东西后悔了,我们可以让玩家去撤销操作。

在编写游戏工具给策划同事使用的时候,没有撤销功能的话会被亲爱的策划骂成狗的。


。。。

等等上面的需求出现之后,我们就可以考虑运用我们的命令模式来解决这个问题。


命令模式的宗旨是让命令类化,为了解耦,命令类将利用ConreteCommand类脱离宿主(接受命令的人,Reciver)的束缚,仅提供的是能够传入宿主的方法,自成一体。而命令与宿主之间的联系是靠一个Invoker来进行命令分发到宿主的。,Invoker里面包涵类的实例化,实例化的时候才挂钩命令与宿主。实例化命令之后就能够进行命令的调用了。

而作为最上层的调用客户,我们就是利用Invoker来进行操作的。


在我的这个例子里面,要演示的是如何利用命令模式去实现回退与重复。

小方块能够在移动之后利用UNDO返回之前的地点,也能利用REDO继续最后一步的时候的方向。




ClickTest.cs 按钮操作的类,Client

Command.cs 命令的抽象

ConcreteCommands.cs 具体的命令。

Cube.cs 方块的类,类里有各个方向移动的方法而已。

CubeController.cs  这家伙就是Invoker了,里面有一个命令的数组,保存命令只用,还有因为要去关联我们宿主,必须要有属性指向我们的Cube.Invoker的调用分三块,Undo,Redo,Go.分别对应三大类型的移动。

CubeEvent.cs 只是一个Enum而已,定义我们的方向。


链接:http://pan.baidu.com/s/1mg3Qgvm


附录代码:

using UnityEngine;
using System.Collections;

public class ClickTest : MonoBehaviour {
    public GameObject user;
	// Use this for initialization
	void Start () {
	    
	}
    public void LeftClick()
    {
        user.GetComponent<CubeController>().LetCubeMove((int)MoveEvent.left);
    }
    public void RightClick()
    {
        user.GetComponent<CubeController>().LetCubeMove((int)MoveEvent.right);
    }
    public void UpClick()
    {
        user.GetComponent<CubeController>().LetCubeMove((int)MoveEvent.up);
    }
    public void DownClick()
    {
        user.GetComponent<CubeController>().LetCubeMove((int)MoveEvent.down);
    }
    public void UndoClick()
    {
        user.GetComponent<CubeController>().Undo();
    }
    public void RedoClick()
    {
        user.GetComponent<CubeController>().Redo();
    }
}
using UnityEngine;
using System.Collections;
//Invoker
public class CubeController : MonoBehaviour {

    public GameObject _cube;
    private ArrayList commands = new ArrayList();
    private int  current = 0;
    public void Redo()
    {

            if (current>0)
            {
                Debug.Log("I can Redo now");
                
                ((MoveCommand)commands[commands.Count-1]).execute();
                commands.Add(commands[commands.Count - 1]);
                current++;
            }
            else
            {
                Debug.Log("当前没有前置行为");
            }
        
    }
    public void Undo()
    {
       
        //Debug.Log("Undo " + levels + "levels");

            if (current > 0)
            {
                Debug.Log("Current comm" + current);
                int bakindex = current;
                ((MoveCommand)commands[--current]).unexecute();
                Debug.Log("往前一步的下标:"+bakindex+",当前下标:"+current);
                commands.RemoveAt(bakindex-1);
            }

    }

    public void LetCubeMove(int move)
    {
        ICommand comm = new MoveCommand(move, _cube);
        comm.execute();
        commands.Add(comm);
        Debug.Log("总命令数为:"+commands.Count);
        current++;
    }
}


using UnityEngine;
using System.Collections;
//Reciver Cube
public class Cube : MonoBehaviour {


    public void OnMove(int move)
    {
        switch (move)
        {
            case 0 :
                MoveForward();
                break;
            case 1: 
                MoveBack();
                break;
            case 2:
                MoveLeft();
                break;
            case 3:
                MoveRight();
                break;
        }
    }
    public void MoveForward()
    {
        gameObject.transform.localPosition += new Vector3(0, 0, 1);
    }
    public void MoveBack()
    {
        gameObject.transform.localPosition += new Vector3(0, 0, -1);
    }
    public void MoveLeft()
    {
        gameObject.transform.localPosition += new Vector3(-1, 0, 0);
    }
    public void MoveRight()
    {
        gameObject.transform.localPosition += new Vector3(1, 0, 0);
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
//ConcreteCommand 定义一个接受者和行为之间的弱耦合
class MoveCommand :ICommand
{
    //Cube is a Reciver 
    private  GameObject Cube;
    public int _move;
    public MoveCommand(int move,GameObject cube)
    {
        this.Cube = cube;
        _move = move;
    }
    public void execute()
    {
        Cube.GetComponent<Cube>().OnMove(_move);
    }

    public void unexecute()
    {
        Cube.GetComponent<Cube>().OnMove(Undo(_move));
    }
    public int  Undo(int move)
    {
        int UnMove = -1;
        switch (move)
        {
        case (int)MoveEvent.up:
                UnMove=(int)MoveEvent.down;
        	break;
         case (int)MoveEvent.down:
                UnMove=(int)MoveEvent.up;
        	break;
            case (int)MoveEvent.left:
                UnMove=(int)MoveEvent.right;
                break;
            case (int)MoveEvent.right:
                UnMove=(int)MoveEvent.left;
                break;
        }
        return UnMove;
    }
}
using UnityEngine;
using System.Collections;

//创建了一个具体命令(ConcreteCommand)对象并确定其接收者
 interface     ICommand {

      void execute();
      void unexecute();  
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public enum MoveEvent
{
    up,
    down,
    left,
    right
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值