遊戲編程設計模式-命令模式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
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章