服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - Unity常用命令模式详解

Unity常用命令模式详解

2022-07-11 08:26探求虚无 C#

这篇文章主要为大家详细介绍了Unity常用命令模式的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

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

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

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

Unity常用命令模式详解

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

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

Unity常用命令模式详解

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

Unity常用命令模式详解

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

Unity常用命令模式详解

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

Unity常用命令模式详解

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

一、接口

?
1
2
3
4
5
public interface ICommand
{
  void Execute();
  void UnDo();
}

二、执行器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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();
    }
  }
}

三、配制加载器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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--;
  }
 
}

四、颜色转换命令脚本

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();
  }
}

五、移动命令脚本

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
  }
}

六、转换命令脚本

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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();
    }
  }
}

七、文字加载脚本

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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

延伸 · 阅读

精彩推荐
  • C#C#编写Windows服务程序详细步骤详解(图文)

    C#编写Windows服务程序详细步骤详解(图文)

    本文介绍了如何用C#创建、安装、启动、监控、卸载简单的Windows Service 的内容步骤和注意事项,需要的朋友可以参考下...

    C#教程网5942022-01-22
  • C#C#中委托的基本用法总结

    C#中委托的基本用法总结

    以下是对C#中委托的基本用法进行了详细的总结分析,需要的朋友可以过来参考下。希望对大家有所帮助...

    C#教程网10262021-01-04
  • C#C#中Timer使用及解决重入问题

    C#中Timer使用及解决重入问题

    本文主要介绍了C#中Timer使用及解决重入问题的相关知识。具有很好的参考价值,下面跟着小编一起来看下吧...

    刘来来8322021-12-27
  • C#C#圆角窗体简单实现方法

    C#圆角窗体简单实现方法

    这篇文章主要介绍了C#圆角窗体简单实现方法,涉及C#窗体设置的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    我心依旧4192021-10-25
  • C#Unity shader实现高斯模糊效果

    Unity shader实现高斯模糊效果

    这篇文章主要为大家详细介绍了Unity shader实现高斯模糊效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    贪玩的孩纸时代6572022-03-11
  • C#C#计算2个字符串的相似度

    C#计算2个字符串的相似度

    这篇文章主要为大家详细介绍了C#计算2个字符串相似度的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    冰封一夏4902022-01-06
  • C#c#中的扩展方法学习笔记

    c#中的扩展方法学习笔记

    扩展方法能够向现有类型“添加”方法,而无需创建新的派生类型,重新编译或以其他方式修改原始类型。下面这篇文章主要给大家介绍了关于c#中扩展方...

    alone_alone4292022-03-05
  • C#C#下载歌词文件的同步和异步方法

    C#下载歌词文件的同步和异步方法

    这篇文章主要为大家详细介绍了C#下载歌词文件的同步和异步方法,感兴趣的小伙伴们可以参考一下...

    波谷11672021-11-26