首页 > 编程 > C# > 正文

Unity常用命令模式详解

2020-01-24 00:07:46
字体:
来源:转载
供稿:网友

在调用一些简单的方法实现一系列的动作时,回退的问题比较重要。作为一款用户体验良好的产品而言,有回退功能将显得比较人性化,想想如果我们常用的window,在删除一个文件后无法恢复将变得多么的糟糕。更为直观的例子是在玩一些小游戏时,比如象棋、推箱子,提供了悔棋的功能,用户有了更多选择的余地。

本文主要将的将是在Unity中实现一个以常听说的命令模式为设计原理,实现一个可以撤销移动、旋转、颜色和文字信息的小Demo。

命令模式,主要成员有提出要求的客户、设置命令的收集者、执行命令的接收者。客户要求很简单,点击按扭就要实现一项目具体的效果,设置命令的收集者无需要知道命令如何执行,只需要为执行者做好配制。用命令的执行者将执行一个方法,所有的命令者是继承于有这个方法的接口的类。

抽象到程序代码中,这三类成员分别对应于界面上的用户,RemoteControl (这里是随便命名的),RemoteLoader

先制作如上的界面,方便你比较直观的认识,其中左边两个是用于切换选择不同的命令。下面第一个按扭可以执行选中的命令,第二个按扭可以进行撤销操作。

程序,UGUI面局如下,在Canvas下分别设置了执行者和配制者。

制作好界面之后就可以来实现具体的脚本编辑了,分别创建好接口ICommand,配制脚本RemoteLoader和执行脚本RemoteControl,结构如下:

在Commonds中,分别编写了用于移动,旋转,颜色,文字的脚本

这样一来,就可以实现一个可撤销的命令模式了,效果如下所示:

其中用于保存undo方法和具体怎么undo都是使用Stack来实现的,下面分别是部分代码实现 :

一、接口

public interface ICommand{  void Execute();  void UnDo();}

二、执行器

public class RemoteControl : MonoBehaviour {  public Button ctrlBtn;  public Button undoBtn;  public Text ctrlName;  private ICommand icommand;  public Stack<UnityAction> undoFunctions = new Stack<UnityAction>();  void Awake(){    ctrlBtn.onClick.AddListener(OnCtrlBtnClicked);    undoBtn.onClick.AddListener(OnUnDoBtnClicked);  }    public void SetText(string textinfo)  {    ctrlName.text = textinfo;  }  public void SetCommond(ICommand icommand)  {    this.icommand = icommand;  }  /// <summary>  /// 执行  /// </summary>  public void OnCtrlBtnClicked()  {    if (icommand != null)    {      icommand.Execute();      undoFunctions.Push(icommand.UnDo);    }  }  /// <summary>  /// 撤销  /// </summary>  private void OnUnDoBtnClicked()  {    if (undoFunctions.Count > 0)    {      undoFunctions.Pop().Invoke();    }  }}

三、配制加载器

public class RemoteLoader : MonoBehaviour{  public Button lastBtn;  public Button nextBtn;  private int index;  private const int NUM_COMMAND = 10;  private ICommand[] commands;  private string[] textinfos;  private MoveCommand movexCmd;  private MoveCommand moveyCmd;  private MoveCommand movezCmd;  private RotateCommand rotxCmd;  private RotateCommand rotyCmd;  private RotateCommand rotzCmd;  private ColorChangeCommand redColorCmd;  private ColorChangeCommand greenColorCmd;  private ColorChangeCommand blueColorCmd;  private TextChangeCommand textCmd;  private string[] infos = { "A","B", "C", "D", "E", "F" };  public RemoteControl remoteCtrl;  public GameObject cube;  void Awake()  {    lastBtn.onClick.AddListener(OnLastBtnClicked);    nextBtn.onClick.AddListener(OnNextBtnClicked);  }  void Start()  {    commands = new ICommand[NUM_COMMAND];    textinfos = new string[NUM_COMMAND];    textinfos[0] = "x方向移动";    commands[0] = new MoveCommand(cube.transform, Vector3.right);    textinfos[1] = "y方向移动";    commands[1] = new MoveCommand(cube.transform, Vector3.up);    textinfos[2] = "z方向移动";    commands[2] = new MoveCommand(cube.transform, Vector3.forward);    textinfos[3] = "x轴旋转10度";    commands[3] = new RotateCommand(cube.transform, Vector3.right * 10);    textinfos[4] = "y轴旋转10度";    commands[4] = new RotateCommand(cube.transform, Vector3.up * 10);    textinfos[5] = "z轴旋转10度";    commands[5] = new RotateCommand(cube.transform, Vector3.forward * 10);    textinfos[6] = "变红";    commands[6] = new ColorChangeCommand(Color.red, cube.GetComponent<Renderer>().material);    textinfos[7] = "变绿";    commands[7] = new ColorChangeCommand(Color.green, cube.GetComponent<Renderer>().material);    textinfos[8] = "变蓝";    commands[8] = new ColorChangeCommand(Color.blue, cube.GetComponent<Renderer>().material);    textinfos[9] = "换信息";    commands[9] = new TextChangeCommand(cube.GetComponentInChildren<TextMesh>(), infos);  }  private void OnNextBtnClicked()  {    if (index == NUM_COMMAND || index == -1)    {      index = 0;    }    remoteCtrl.SetCommond(commands[index]);    remoteCtrl.SetText(textinfos[index]);    index++;  }  private void OnLastBtnClicked()  {    if (index == NUM_COMMAND || index == -1)    {      index = NUM_COMMAND - 1;    }    remoteCtrl.SetCommond(commands[index]);    remoteCtrl.SetText(textinfos[index]);    index--;  }}

四、颜色转换命令脚本

public class ColorChangeCommand : ICommand{  private Stack<Color> m_OriginColor = new Stack<Color>();  private Color m_Color;  private Material m_Material;    public ColorChangeCommand(Color color, Material material)  {    m_Color = color;    m_Material = material;  }  public void Execute()  {    m_OriginColor.Push(m_Material.color);    m_Material.color = m_Color;  }  public void UnDo()  {    m_Material.color = m_OriginColor.Pop();  }}

五、移动命令脚本

public class MoveCommand : ICommand{  private Vector3 m_Offset;  private Transform m_Object;  public MoveCommand(Transform obj, Vector3 offset)  {    this.m_Object = obj;    this.m_Offset = offset;  }  public void Execute()  {    m_Object.transform.position += m_Offset;  }  public void UnDo()  {    m_Object.transform.position -= m_Offset;  }}

六、转换命令脚本

public class RemoteControl : MonoBehaviour {  public Button ctrlBtn;  public Button undoBtn;  public Text ctrlName;  private ICommand icommand;  public Stack<UnityAction> undoFunctions = new Stack<UnityAction>();  void Awake(){    ctrlBtn.onClick.AddListener(OnCtrlBtnClicked);    undoBtn.onClick.AddListener(OnUnDoBtnClicked);  }    public void SetText(string textinfo)  {    ctrlName.text = textinfo;  }  public void SetCommond(ICommand icommand)  {    this.icommand = icommand;  }  /// <summary>  /// 执行  /// </summary>  public void OnCtrlBtnClicked()  {    if (icommand != null)    {      icommand.Execute();      undoFunctions.Push(icommand.UnDo);    }  }  /// <summary>  /// 撤销  /// </summary>  private void OnUnDoBtnClicked()  {    if (undoFunctions.Count > 0)    {      undoFunctions.Pop().Invoke();    }  }}

七、文字加载脚本

public class TextChangeCommand : ICommand{  private Stack<string> lastInfos = new Stack<string>();  private IEnumerator<string> datas;  private TextMesh m_Textmesh;  public TextChangeCommand(TextMesh textMesh,ICollection<string> texts)  {    datas = texts.GetEnumerator();    m_Textmesh = textMesh;  }  public void Execute()  {    if (!datas.MoveNext())    {      datas.Reset();      datas.MoveNext();    }    lastInfos.Push(m_Textmesh.text);    m_Textmesh.text = datas.Current;  }  public void UnDo()  {    m_Textmesh.text = lastInfos.Pop();  }}

仅供参考,谢谢阅读。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表