1.指令模式的意義。
模式是爲了解決問題而生,他讓編程流程化,面相對象話,系統模塊話,讓人易於讀,易於寫,易於擴展,易於修改,軟件邏輯,尤其複雜點的遊戲世界,它的邏輯更是千奇百遍,策劃的思路有時候更是天馬行空。所以爲了解決這些問題,人們約定俗成了一樣設計思路,即設計模式。但是也不能一味的套用設計模式,他也同時只是一種思想,跟古代的兵法一樣,虛虛實實,伺機而動。而今天所說的指令模式,其實說白了就是對指令的一種封裝,用人們常說的一句話就是,指令就像餐廳裏面的菜單一樣,顧客到餐廳裏面點餐,服務員一一給顧客介紹各種美味的涼菜,熱菜,飲料等等。然後顧客決定我要吃涼拌黃瓜,農家小炒肉,還有一杯扎啤,然後服務員就給顧客下訂單了,像廚房pos機器發送指令了,A指令:發給涼菜師傅,讓涼菜師傅做涼拌黃瓜,B指令:發給熱菜師傅,做農家小炒肉,C指令:發給一個服務員,弄一杯扎啤。這樣就形成了完整的指令模式。
在我們的遊戲設計中,如ACT格鬥遊戲中,我們可以用指令模式來設計各種操作的交互,我們可以把普工,技能攻擊,跑,跳,等操作封裝爲command命令,當玩家操縱遙感的時候,就可以像操作對象來發送各種指令,我們可以通過一個Invoke的路由器來管理這些指令,在時候的時候執行這些命令,我們來封裝一個簡單的指令接口。
using System;
using UnityEngine;
public interface CommandBase
{
void execute(GameObject gameObjects);
void unexecute(GameObject gameObjects);
}
這是一個指令的接口,他的基類必須要實現這2個方法,這兩個方法主要是提供給路由器也就是Invoke服務員,讓他等待顧客下完訂單之後,她在生成命令,在調用execute方法來執行命令,如果客人反悔了怎麼辦,就調用unexecute 來撤銷訂單。我們在來實現一個命令的接口,如下實現一個移動的命令,繼承自CommandBasepublic class MoveCommand : CommandBase
{
public void execute(GameObject gameObjects)
{
Debug.Log ("我在移動+++++++++++++++++++");
}
public void unexecute(GameObject gameObjects)
{
Debug.Log ("我要移動回去+++++++++++++++++++");
}
}
這是一個完整的基本的移動command,即當Invoker來執行命令的時候,移動command就會調用 GameObject 的移動方法來進行移動。當撤銷的時候,就可以調用unexecute 方法來進行移動回去等,這些具體的實現需要根據你的業務邏輯來進行實現。同理,我們來實現一個攻擊命令。using System;
using UnityEngine;
public class AttackCommand : CommandBase
{
public void execute(GameObject gameObjects)
{
Debug.Log ("我要攻擊你,攻擊你+++++++++++++");
}
public void unexecute(GameObject gameObjects)
{
Debug.Log ("我不攻擊你了,我要撤回去,++++++++++++");
}
}
好了,我們已經實現了兩個最簡單的大概的命令,我們來實現invoker方法。using System;
using System.Collections.Generic;
using UnityEngine;
//命令的隊列 命令的發送者我給成一個單例 到底應不應該是個單利 這個根據業務邏輯來定義了
public class CommandInvoke
{
public GameObject m_GameObejects;
private CommandBase m_BackCommand;
Queue<CommandBase > comandList = new Queue<CommandBase> ();
public void setComamnd(CommandBase comandBase,GameObject riverObejcts)
{
m_GameObejects = riverObejcts;
comandList.Enqueue(comandBase);
}
//執行命令 執行完成之後在看隊列裏面還有沒有命令 沒有命令則繼續執行
public void execute()
{
if (comandList.Count > 0)
{
foreach(var commands in comandList )
{
m_BackCommand = commands;
commands.execute (m_GameObejects);
}
}
comandList.Clear ();
}
/// <summary>
/// 撤銷方法
/// </summary>
public void UnDone()
{
m_BackCommand.unexecute (m_GameObejects);
}
}
這個方法其實也很簡單,就是用來管理命令的,還是根據你的邏輯來進行編寫,你可以寫一個隊列,把玩家操作的命令都添加到隊列裏面去,執行完一個在執行下一個,或者都同時執行,等等。看看簡不簡單了。我們來實現一個測試的方法。
using System;
using UnityEngine;
using UnityEngine.UI;
public class TestComand :MonoBehaviour
{
public GameObject m_GameObjects;
private CommandInvoke m_Invoke;
void Start()
{
m_Invoke = new CommandInvoke ();
}
public void BtnClickMove()
{
CommandBase moveComand = new MoveCommand ();
m_Invoke.setComamnd (moveComand,m_GameObjects);
m_Invoke.execute ();
}
public void BtnClickAttack()
{
CommandBase sclaeCommands = new AttackCommand ();
m_Invoke.setComamnd (sclaeCommands,m_GameObjects);
m_Invoke.execute ();
}
}
這樣,就可以根據玩家不同的操作來發送不同的指令,同時在Invoker裏面來管理這些指令。是不是很簡單啊,這樣你也就完全不用關心接收者了,只用來組裝自己的命令,發送命令,重點在於要解耦“請求的發送者”和“請求的執行者”。
- 重點在於要解耦“請求的發送者”和“請求的執行者”