软件编程
位置:首页>> 软件编程>> C#编程>> Unity常用命令模式详解

Unity常用命令模式详解

作者:探求虚无  发布时间:2021-12-30 16:58:08 

标签:Unity,命令模式

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

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

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

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

Unity常用命令模式详解

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

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

Unity常用命令模式详解

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

Unity常用命令模式详解

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

Unity常用命令模式详解

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

Unity常用命令模式详解

其中用于保存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();
 }
}

仅供参考,谢谢阅读。

来源:https://blog.csdn.net/tankerhunter/article/details/52058054

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com