我们专注攀枝花网站设计 攀枝花网站制作 攀枝花网站建设
成都网站建设公司服务热线:400-028-6601

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

如何在Unity3D中使用撤回命令

如何在Unity3D中使用撤回命令?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

创新互联自2013年创立以来,先为伊金霍洛等服务建站,伊金霍洛等地企业,进行企业商务咨询服务。为伊金霍洛企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。

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

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

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

public class CommandManager : MonoBehaviour
{
 public static CommandManager Instance = null;
 //管理命令
 private Stack commandStack = new Stack();
 
 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();
  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 objects;
 
 public DestoryCommand(List objects)
 {
  this.objects = objects;
 }
 
 public override void RevocationCommand()
 {
  for(int i=0;i< objects.Count;i++)
  {
   //利用对象池技术回收物体 这里就不写了 因为还要把对象池的脚本添加进来
  }
 }
}

关于如何在Unity3D中使用撤回命令问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。


网站名称:如何在Unity3D中使用撤回命令
文章URL:http://shouzuofang.com/article/ghgogc.html

其他资讯