C# 如何使用Unity3D在运行时设置撤消/重做系统

C# 如何使用Unity3D在运行时设置撤消/重做系统,c#,unity3d,system,undo-redo,C#,Unity3d,System,Undo Redo,我试图在运行时设置撤消/重做系统,但无法使代码正常工作。我已经创建了一个撤销按钮,但当我移动游戏对象并按下撤销按钮时,游戏对象不会返回其原始状态 我只是希望最终用户能够在运行时和编辑器模式下撤销/重做其最新操作。我做了几次尝试,尝试了许多不同的脚本,但没有取得任何进展。有什么建议吗 using System.Collections; using System.Collections.Generic; using UnityEngine; public class undoit : MonoBe

我试图在运行时设置撤消/重做系统,但无法使代码正常工作。我已经创建了一个撤销按钮,但当我移动游戏对象并按下撤销按钮时,游戏对象不会返回其原始状态

我只是希望最终用户能够在运行时和编辑器模式下撤销/重做其最新操作。我做了几次尝试,尝试了许多不同的脚本,但没有取得任何进展。有什么建议吗

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class undoit : MonoBehaviour
{
    public class setting
    {
        public GameObject Obj;
        public Vector3 Pos;
        public Quaternion Rot;
        public bool Deleted;

        public void Restore()
        {
            Obj.transform.position = Pos;
            Obj.transform.rotation = Rot;
            Obj.SetActive(Deleted);
        }
        public setting(GameObject g)
        {
            Obj = g;
            Pos = g.transform.position;
            Rot = g.transform.rotation;
            Deleted = g.activeSelf;
        }
    }
    public List<setting> UndoList;

    public void AddUndo(GameObject g)
    {
        setting s = new setting(g);
        UndoList.Add(s);
    }
    public void Undo()
    {
        if (UndoList.Count > 0)
        {
            UndoList[UndoList.Count - 1].Restore();
            UndoList.RemoveAt(UndoList.Count - 1);
        }
    }
    void Start()
    {
        UndoList = new List<setting>();
    }
}
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
公共类撤销:单一行为
{
公共班级设置
{
公共游戏对象Obj;
公共向量机3 Pos;
公共四元数;
删除公共文件;
公共无效恢复()
{
Obj.transform.position=Pos;
Obj.transform.rotation=Rot;
Obj.SetActive(已删除);
}
公共设置(游戏对象g)
{
Obj=g;
Pos=g.变换位置;
Rot=g.transform.rotation;
删除=g.activeSelf;
}
}
公开名单;
公共无效添加撤消(游戏对象g)
{
设置s=新设置(g);
撤消列表。添加(s);
}
公共作废撤消()
{
如果(UndoList.Count>0)
{
UndoList[UndoList.Count-1].Restore();
RemoveAt(UndoList.Count-1);
}
}
void Start()
{
UndoList=新列表();
}
}

首先,您需要一些可以存储相关数据的东西,例如

public struct ObjectState
{
    // The transform this data belongs to
    private Transform transform;

    private Vector3 localPosition;
    private Quaternion localRotation;
    private Vector3 localScale;

    private bool active;

    public ObjectState (GameObject obj)
    {
        transform = obj.transform;
        localPosition = transform.localPosition;
        localRotation = transform.localRotation;
        localScale = transform.localScale;

        active = obj.activeSelf;
    }

    public void Apply()
    {
        transform.localPosition = localPosition;
        transform.localRotation = localRotation;
        transform.localScale = localScale;

        transform.gameObject.SetActive(active);
    }
}
接下来,我将使用包装器类来存储可撤消的更改,如

public struct UndoableChange
{
    private ObjectState _before;
    private ObjectState _after;

    public UndoableChange (ObjectState before, ObjectState after)
    {
        _before = before;
        _after = after;
    }

    public void Undo()
    {
        _before.Apply();
    }   

    public void Redo()
    {
        _after.Apply();
    }     
}
或者,如果您需要立即将其用于我的对象,您可以使用列表,例如

public struct UndoableChange
{
    private List<ObjectState> _before;
    private List<ObjectState> _after;

    public UndoableChange (List<ObjectState> before, List<ObjectState> after)
    {
        _before = before;
        _after = after;
    }

    public void Undo()
    {
        foreach(var state in _before)
        {
            state.Apply();
        }
    }   

    public void Redo()
    {
        foreach(var state in _after)
        {
            state.Apply();
        }
    }     
}
// at some point store the initial values
var before = new ObjectState (selectedGameObject);

//TODO Apply all your changes to the selected object 

// get the new values
var after = new ObjectState (selectedGameObject);

// Log to the history
UndoRedo.AddAction(new UndoableChange(before, after));
我不知道你的用户到底是如何与对象交互的,但你现在总是会这样做

public struct UndoableChange
{
    private List<ObjectState> _before;
    private List<ObjectState> _after;

    public UndoableChange (List<ObjectState> before, List<ObjectState> after)
    {
        _before = before;
        _after = after;
    }

    public void Undo()
    {
        foreach(var state in _before)
        {
            state.Apply();
        }
    }   

    public void Redo()
    {
        foreach(var state in _after)
        {
            state.Apply();
        }
    }     
}
// at some point store the initial values
var before = new ObjectState (selectedGameObject);

//TODO Apply all your changes to the selected object 

// get the new values
var after = new ObjectState (selectedGameObject);

// Log to the history
UndoRedo.AddAction(new UndoableChange(before, after));
或相应地使用所有选定对象的列表,例如,仅使用
Linq

using System.Linq;

...

var before = selectedGameObjects.Select(obj => new ObjectState(obj)).ToList();

//TODO Apply all your changes to all the selected objects 

var after = selectedGameObjects.Select(obj => new ObjectState(obj)).ToList();

UndoRedo.AddAction(new UndoableChange(before, after));


注意:在智能手机上输入,但我希望想法变得清晰

你确定你在每一步都记住了所有更改的内容吗?现在,我只想更改一个步骤,看看代码是否正常工作。如果你没有记住更改前的所有状态,以及要放回什么。。。1个或多个是不相关的我假设我的代码太简单,无法使用撤销…我对此表示怀疑,不管它有多复杂或简单,你都需要记住之前的所有内容,然后返回到它。。现在还不清楚你改变了什么,只是你储存了一些信息,可能不止这些。。你也没有解释它以什么方式不起作用哇!谢谢你的回复。我真的很感谢你的解释和编码。我会看看我是否能将你的代码实现到我的脚本中。我在代码中有一些错误。一个是var lastAction.*Undo*();。另一个是public*UndoableChange*(ObjectState before,ObjectState after)。最后是UndoRedo.AddAction(新的UndoableChange(before,after));。刚刚更新了答案。。
公共类ObjectState
缺少
,字段必须以
开头的方法)正如我所说的,我只是在pH上,所以有时我会有一些打字错误:“出于某种原因,我在UndoRedo.AddAction(new UndoableChange(before,after))上仍然收到一个错误;上面说什么?