環境:Unity2021.1.14 Odin3.0.4 語言:C#
面向:Editor開發人員
文章參考:
http://49.233.81.186/undo.html
總起
前接上文,這次介紹一下組的概念和一個效果實作的實踐,
組的概念
嘗試以下代碼:
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;
public class Test3 : MonoBehaviour
{
public float fValue = 0f;
[Button]
public void ChangeValueTwice()
{
Undo.RecordObject(this, "Change Value 1");
fValue = 1;
Undo.RecordObject(this, "Change Value 2");
fValue = 2;
}
}
點擊ChangeValueTwice,再按Ctrl+Z撤銷,我們可以看到注冊的兩次Undo合并成了一個同時被撤銷了,
在撤銷時,PropertyDiffUndoRecorder會將上述兩次操作組合到一起,直到執行Flush,
如果需要單獨運行每個撤銷,可以在記錄完物件后呼叫Undo. IncrementCurrentGroup方法,
同樣的我們也可以合并多次撤銷:
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;
public class Test3 : MonoBehaviour
{
private bool startChange = false;
private int groupId = 0;
public int iValue1;
public int iValue2;
private void TryStartChange()
{
if (!startChange)
{
startChange = true;
groupId = Undo.GetCurrentGroup();
}
}
[Button]
public void ChangeValue1()
{
TryStartChange();
Undo.RecordObject(this, "Change Value 1");
iValue1++;
}
[Button]
public void ChangeValue2()
{
TryStartChange();
Undo.RecordObject(this, "Change Value 2");
iValue2++;
}
[Button]
public void EndChange()
{
Undo.CollapseUndoOperations(groupId);
}
}
點擊ChangeValue1和ChangeValue2程序中進行撤銷,每次都是直接回到上一步,但是只要點擊了EndChange,再按撤銷就直接回到了初始狀態,
實作任意物件的Undo
我們在實作物件的Undo的時候,通常繼承于MonoBehavior系列的類都是自帶Undo的,但是有時候需要針對自定義的物件做Undo,那應該怎么做呢?
我們來看一下以下代碼:
using System;
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;
public class TestUndo3 : MonoBehaviour
{
public Undo3WrapData wrapData;
[Button]
public void CreateData()
{
wrapData = ScriptableObject.CreateInstance<Undo3WrapData>();
}
[Button]
public void ChangeData()
{
Undo.RecordObject(wrapData, "change undo3");
wrapData.data.iValue++;
Debug.Log("iValue change to " + wrapData.data.iValue);
}
[Button]
public void PrintData()
{
Debug.Log("iValue: " + wrapData.data.iValue);
}
}
public class Undo3WrapData : ScriptableObject
{
public Undo3Data data = new Undo3Data();
}
[Serializable]
public class Undo3Data
{
public int iValue;
}
點擊CreateData,再點擊三次ChangeData,然后多按幾次ctrl+z和PrintData:

我們可以看到Undo3Data并不是UnityObject物件,但通過Undo3WrapData也正確實作了Undo,
當然這個例子有很大的局限性,我這邊只是給大家理一下思路,
同樣,如果甚至不想在Undo3Data上打上Serializable標簽,那么可以自己實作序列化:
public class Undo3WrapData : ScriptableObject, ISerializationCallbackReceiver
{
public string serializedData;
public Undo3Data data = new Undo3Data();
public void OnBeforeSerialize()
{
serializedData = "iValue:" + data.iValue;
}
public void OnAfterDeserialize()
{
if (string.IsNullOrEmpty(serializedData))
{
return;
}
data.iValue = int.Parse(serializedData.Split(':')[1]);
}
}
public class Undo3Data
{
public int iValue;
}
Json的什么或者將操作程序式進行序列化就由大家各自發揮了,
主要注意的是前一篇博客中說的“Profiler中的一些細節”,講了一些性能問題,大家如果想使用這種方式可以參考一下,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/292833.html
標籤:其他
