Unity3D撤回命令开发详解

 更新时间:2020年6月25日 10:37  点击:1962

本文实例为大家分享了Unity3D撤回命令功能开发,供大家参考,具体内容如下

在类似操作考核的项目中我们经常会遇到回到上一步的需求。所以我们有必要对每一个状态点的所有参与交互的物体的状态进行记录。好了,下面就是代码的实现:

首先肯定要创建命令的基类,

public class BaseCommand
{
 
 //执行命令
 public virtual void ExcuteCommand() { }
 
 
 //撤销命令
 public virtual void RevocationCommand() { }
 
}

因为我们控制物体的类似移动改变方式不同,有可能是直接移动的,有可能是用的dotween来操作移动,所以我们的执行命令函数可能对于我们没有实现的必要。下面我们要创建一个用来管理命令的脚本,供我们添加和移除命令,同时这个脚本我们给设置为单例,可供全局调用。如下:

public class CommandManager : MonoBehaviour
{
 public static CommandManager Instance = null;
 //管理命令
 private Stack<BaseCommand> commandStack = new Stack<BaseCommand>();
 
 private void Awake()
 {
  Instance = this;
 }
 
 
 //增加命令 
 public void AddCommand(BaseCommand baseCommand)
 {
  commandStack.Push(baseCommand);
 }
 
 
 //移除命令 并且撤销一步操作
 public void RemoveCommand()
 {
  if(commandStack.Count>0)
  {
   BaseCommand baseCommand = commandStack.Pop();
   baseCommand.RevocationCommand();
  }
 }
}

有个命令基类,有了管理类,下面我们就要对不同命令进行专门的功能实现了。

一.移动类命令

//保存模型的位置 角度 大小信息
public class TransformCommand : BaseCommand
{
 private Transform target;
 private Vector3 pos;
 private Vector3 rota;
 private Vector3 scale;
 private Transform parent;
//我们在构造函数里直接传进来我们改变状态前的Transform信息
 public TransformCommand(Transform target, Vector3 pos, Vector3 rota, Vector3 scale,Transform parent)
 {
  this.target = target;
  this.pos = pos;
  this.rota = rota;
  this.scale = scale;
  this.parent = parent;
 }
 
 public override void ExcuteCommand()
 {
  base.ExcuteCommand();
 }
 
 public override void RevocationCommand()
 {
  target.SetParent(parent);
  target.transform.localPosition = pos;
  target.transform.localEulerAngles = rota;
  target.transform.localScale = scale;
 }
}

下面是我们写的测试脚本挂在到摄像头上,

public class CameraMove : MonoBehaviour {
 
 
 // Update is called once per frame
 void Update ()
 {
  if(Input.GetKeyDown(KeyCode.W))
  {
   TransformCommand cmd = new TransformCommand(transform,transform.localPosition,
    transform.localEulerAngles,transform.localScale,null);
   CommandManager.Instance.AddCommand(cmd);
   transform.Translate(Vector3.forward,Space.Self);
  }
 }
}

还需要写一个输入的类来调用撤退命令,代码如下:

public class Test : MonoBehaviour {
 
 private void Update()
 {
  if(Input.GetKeyDown(KeyCode.Escape))
  {
   CommandManager.Instance.RemoveCommand();
  }
 }
}

二.UI类用户控制改变状态

下面以InputField为例,介绍UI交互类的撤退命令,这个要比普通的麻烦一些。我找了官方文档好久也没发现值改变前得回掉函数,所以只能自己来实现了。首先我们要自己写一个脚本用来记录改变之前的值。挂载在场景里的InputField上。代码如下:

public class MyInputField : MonoBehaviour,IPointerClickHandler
{
 private InputField input;
 private string preString;//用来记录改变前得值
 
 private bool IsValueChange = false;//判断值是否发生改变
 
 private bool IsClick = false;//用来判断InputField是否被选中交互
 
 
 
 private void Awake()
 {
  input = GetComponent<InputField>();
  input.onValueChanged.AddListener(delegate { IsValueChange=true; });
  input.onEndEdit.AddListener(OnEndEditCallBck);
 }
 
 //结束编辑得回调函数
 void OnEndEditCallBck(string content)
 {
  IsClick = false;
  //如果值没变 直接返回 没必要增加命令
  if (IsValueChange == false) return;
  InputFieldCommand cmd = new InputFieldCommand(input,preString);
  CommandManager.Instance.AddCommand(cmd);
 }
 
 //当被点击时,我们的UI组件被交互 有被更改值得可能 所以要记录当前值
 public void OnPointerClick(PointerEventData eventData)
 {
  Debug.Log("点击");
  if (IsClick) return;
  preString = input.text;
  IsClick = true;
 }
}
public class InputFieldCommand : BaseCommand
{
 private InputField targetInput;
 private string content;
 
 
 public InputFieldCommand(InputField inputField,string content)
 {
  this.targetInput = inputField;
  this.content = content;
 }
 
 
 public override void RevocationCommand()
 {
  base.RevocationCommand();
  targetInput.text = content;
 }
}

上面就是在用户对InputField输入内容改变时自动记录上一步得命令。对于其他得UI组件类似Toggle Slider同样适用。

三.销毁生成的物体

我们在当前一步实例化很多物体,返回上一步就需要销毁所有实例化的物体。这里我们不建议直接销毁,而是利用对象池技术进行回收,还节约性能。对象池技术博客地址:点击打开链接  代码如下:

public class DestoryCommand : BaseCommand
{
 private List<GameObject> objects;
 
 public DestoryCommand(List<GameObject> objects)
 {
  this.objects = objects;
 }
 
 public override void RevocationCommand()
 {
  for(int i=0;i< objects.Count;i++)
  {
   //利用对象池技术回收物体 这里就不写了 因为还要把对象池的脚本添加进来
  }
 }
}

这个命令是在我们实例化物体后才能增加。其实就是把实例化的物体加入到List数组然后传入一个新声明的DestoryCommand构造函数中。以上效果图如下:

希望本博客对你有帮助!

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

[!--infotagslink--]

相关文章

  • Unity3D UGUI实现翻书特效

    这篇文章主要为大家详细介绍了Unity3D UGUI实现翻书特效,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D实现飞机大战游戏(1)

    这篇文章主要为大家详细介绍了Unity3D实现飞机大战游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-11-03
  • Unity3D使用GL实现图案解锁功能

    这篇文章主要为大家详细介绍了Unity3D使用GL实现图案解锁功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D游戏开发数据持久化PlayerPrefs的用法详解

    在本篇文章里小编给大家整理了关于Unity3D游戏开发之数据持久化PlayerPrefs的使用的相关知识点内容,需要的朋友们参考下。...2020-06-25
  • Unity3D基于OnGUI实时显示FPS

    这篇文章主要介绍了Unity3D基于OnGUI实时显示FPS,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D仿写Button面板事件绑定功能

    这篇文章主要为大家详细介绍了Unity3D仿写Button面板事件绑定功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • unity3D实现三维物体跟随鼠标

    这篇文章主要为大家详细介绍了unity3D实现三维物体跟随鼠标,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • unity3d调用手机或电脑摄像头

    这个是在网上看到的,经测试可以在电脑上运行,确实调用了本地摄像头。有需要的小伙伴可以参考下。...2020-06-25
  • Unity3D Shader实现镜子效果

    这篇文章主要为大家详细介绍了Unity3D Shader实现镜子效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D实现待机状态图片循环淡入淡出

    这篇文章主要为大家详细介绍了Unity3D实现待机状态图片循环淡入淡出,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D Shader实现动态屏幕遮罩

    这篇文章主要为大家详细介绍了Unity3D Shader实现动态屏幕遮罩效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D使用UGUI开发原生虚拟摇杆

    这篇文章主要为大家详细介绍了Unity3D使用UGUI开发原生虚拟摇杆,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D UGUI特效之Image高斯模糊效果

    这篇文章主要为大家详细介绍了Unity3D UGUI特效之Image高斯模糊效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D实现物体闪烁效果

    这篇文章主要为大家详细介绍了Unity3D实现物体闪烁效果,类似霓虹灯、跑马灯、LED灯效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D实现分页系统

    这篇文章主要为大家详细介绍了Unity3D实现分页系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D利用DoTween实现卡牌翻转效果

    这篇文章主要为大家详细介绍了Unity3D利用DoTween实现卡牌翻转效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D实现鼠标控制视角转动

    这篇文章主要为大家详细介绍了Unity3D实现鼠标控制视角转动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D生成一段隧道网格的方法

    这篇文章主要为大家详细介绍了Unity3D生成一段隧道网格的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-18
  • Unity3d获取系统时间

    本文通过一段代码给大家详解unity3d获取系统时间,代码简单易懂,小伙伴们快来看看吧...2020-06-25
  • Unity3D动态对象优化代码分享

    这篇文章主要介绍了Unity3D动态对象优化代码分享的相关资料,需要的朋友可以参考下...2020-06-25