Unity3D 基本撤消脚本
Unity3D Basic Undo scripting
目前,我正在尝试在我的游戏中设置一个基本的撤消功能。在我的设置中,我只是试图将游戏对象设置为活动状态,从假到真。我已经添加了 undo.recordobject 以便 unity 可以跟踪更改,但是之后我需要做什么?我想创建一个按钮,允许最终用户撤消之前的操作。我的代码中目前缺少哪些步骤让我的软件执行撤消选项?
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using System;
using UnityEditor;
public class LoadAssets : MonoBehaviour
{
public GameObject Mud;
public GameObject DrillFormationMain;
public GameObject DrillFormation1;
public GameObject DrillFormation2;
public GameObject DrillFormation3;
int count = 0;
public void DrillHole()
{
if (count == 0)
{
Mud.SetActive(true);
DrillFormationMain.SetActive(false);
DrillFormation1.SetActive(true);
Undo.RecordObject(DrillFormationMain, "Change");
DrillFormationMain.transform.position = Vector3.zero;
}
else if (count == 1)
{
DrillFormation1.SetActive(false);
DrillFormation2.SetActive(true);
Undo.RecordObject(DrillFormation1, "Change1");
DrillFormation1.transform.position = Vector3.zero;
}
count++;
}
}
Undo
是 UnityEditor
命名空间的一部分。
此命名空间(因此得名)仅存在于 Unity 编辑器本身中,并在构建中被完全删除
=> 您不能使用其中的任何内容,当然 Undo.RecordObject
用于实际的运行时代码,但只能用于自定义编辑器脚本。
您将不得不为您的 undo/redo 系统想出另一个解决方案。
一个非常简化的示例可能类似于
public class UndoableAction
{
public UndoableActionType Type;
public UnityEngine.Object target;
public object from;
public object to;
public UndoableAction(UndoableActionType type, UnityEngine.Object target, object from, object to)
{
Type = type;
Target = target;
From = from;
To = to;
}
}
public enum UndoableActionType
{
Enable,
SetActive,
Position,
// ... according to your needs
}
public class UndoRedoSystem : MonoBehaviour
{
private Stack<UndoableAction> availableUndos = new Stack<UndoableAction>();
private Stack<UndoableAction> availableRedos = new Stack<UndoableAction>();
public void TrackChangeAction(UndoableActionType type, UnityEngine.Object target, object from, object to)
{
// if you change something redo is cleared
availableRedos.Clear();
// Add this action do undoable actions
availableUndos.Push(new UndoableAction(type, target, from, to));
}
public void Redo()
{
if(availableRedos.Count == 0) return;
// get latest entry added to available Redos
var redo = availableRedos.Pop();
switch(redo.Type)
{
case UndoableActionType.Enable:
((Component) redo.target).enabled = (bool)redo.To;
break;
case UndoableActionType.SetActive:
((GameObject) redo.target).SetActive((bool) redo.To);
break;
case UndoableActionType.Position:
((Transform) redo.target).position = (Vector3) redo.To;
break;
// ... According to your needs
}
// finally this is now a new undoable action
availableUndos.Push(redo);
}
public void Undo()
{
if(availableUndos.Count == 0) return;
// get latest entry added to available Undo
var undo = availableUndos.Pop();
switch(undo.Type)
{
case UndoableActionType.Enable:
((Component) undo.target).enabled = (bool)undo.From;
break;
case UndoableActionType.SetActive:
((GameObject) undo.target).SetActive((bool) undo.From);
break;
case UndoableActionType.Position:
((Transform) undo.target).position = (Vector3) undo.From;
break;
// ... According to your needs
}
// finally this is now a new redoable action
availableRedos.Push(undo);
}
}
现在您可以做一些事情,例如
SomeGameObject.SetActive(true);
undoSystemReference.TrackChange((UnityEngine.Object)SomeGameObject, (object)false, (object)true);
然后在某个地方
undoSystemReference.Undo();
这当然非常简单并且容易出错。
注意 在智能手机上打字,所以没有保修,但我希望这个想法能清楚
目前,我正在尝试在我的游戏中设置一个基本的撤消功能。在我的设置中,我只是试图将游戏对象设置为活动状态,从假到真。我已经添加了 undo.recordobject 以便 unity 可以跟踪更改,但是之后我需要做什么?我想创建一个按钮,允许最终用户撤消之前的操作。我的代码中目前缺少哪些步骤让我的软件执行撤消选项?
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using System;
using UnityEditor;
public class LoadAssets : MonoBehaviour
{
public GameObject Mud;
public GameObject DrillFormationMain;
public GameObject DrillFormation1;
public GameObject DrillFormation2;
public GameObject DrillFormation3;
int count = 0;
public void DrillHole()
{
if (count == 0)
{
Mud.SetActive(true);
DrillFormationMain.SetActive(false);
DrillFormation1.SetActive(true);
Undo.RecordObject(DrillFormationMain, "Change");
DrillFormationMain.transform.position = Vector3.zero;
}
else if (count == 1)
{
DrillFormation1.SetActive(false);
DrillFormation2.SetActive(true);
Undo.RecordObject(DrillFormation1, "Change1");
DrillFormation1.transform.position = Vector3.zero;
}
count++;
}
}
Undo
是 UnityEditor
命名空间的一部分。
此命名空间(因此得名)仅存在于 Unity 编辑器本身中,并在构建中被完全删除
=> 您不能使用其中的任何内容,当然 Undo.RecordObject
用于实际的运行时代码,但只能用于自定义编辑器脚本。
您将不得不为您的 undo/redo 系统想出另一个解决方案。
一个非常简化的示例可能类似于
public class UndoableAction
{
public UndoableActionType Type;
public UnityEngine.Object target;
public object from;
public object to;
public UndoableAction(UndoableActionType type, UnityEngine.Object target, object from, object to)
{
Type = type;
Target = target;
From = from;
To = to;
}
}
public enum UndoableActionType
{
Enable,
SetActive,
Position,
// ... according to your needs
}
public class UndoRedoSystem : MonoBehaviour
{
private Stack<UndoableAction> availableUndos = new Stack<UndoableAction>();
private Stack<UndoableAction> availableRedos = new Stack<UndoableAction>();
public void TrackChangeAction(UndoableActionType type, UnityEngine.Object target, object from, object to)
{
// if you change something redo is cleared
availableRedos.Clear();
// Add this action do undoable actions
availableUndos.Push(new UndoableAction(type, target, from, to));
}
public void Redo()
{
if(availableRedos.Count == 0) return;
// get latest entry added to available Redos
var redo = availableRedos.Pop();
switch(redo.Type)
{
case UndoableActionType.Enable:
((Component) redo.target).enabled = (bool)redo.To;
break;
case UndoableActionType.SetActive:
((GameObject) redo.target).SetActive((bool) redo.To);
break;
case UndoableActionType.Position:
((Transform) redo.target).position = (Vector3) redo.To;
break;
// ... According to your needs
}
// finally this is now a new undoable action
availableUndos.Push(redo);
}
public void Undo()
{
if(availableUndos.Count == 0) return;
// get latest entry added to available Undo
var undo = availableUndos.Pop();
switch(undo.Type)
{
case UndoableActionType.Enable:
((Component) undo.target).enabled = (bool)undo.From;
break;
case UndoableActionType.SetActive:
((GameObject) undo.target).SetActive((bool) undo.From);
break;
case UndoableActionType.Position:
((Transform) undo.target).position = (Vector3) undo.From;
break;
// ... According to your needs
}
// finally this is now a new redoable action
availableRedos.Push(undo);
}
}
现在您可以做一些事情,例如
SomeGameObject.SetActive(true);
undoSystemReference.TrackChange((UnityEngine.Object)SomeGameObject, (object)false, (object)true);
然后在某个地方
undoSystemReference.Undo();
这当然非常简单并且容易出错。
注意 在智能手机上打字,所以没有保修,但我希望这个想法能清楚