We need a Undo/Redo system for our software at runtime. We already have something in place following the Command Design Pattern. We have a basic UndoRedoItem that the manager works with. Inheriting from it, it is possible to create what ever undo redo functionality you need.
One problem is: Everything you want to do needs its custom item. Looking at UndoRedo system tutorials online, they are only utter ■■■■. Like pushing a int to a glogal array<int>.
(Cause the item is responsible for what is going to happen, we also wrapped those items into an action that can be transmitted for multiplayer (No Undo/Redo in multiplayer, but execute needs to happen)).
But having an actual program with lots of different data and different possible transactions, that does not work out nicely.
Another problem: runtime created objects. Making an undo might undo something for an object that does not exist anymore (no tutorial/blog entry handles that problem).
Having a look at Unreals Editor UndoRedo-System (ITransaction/FTransaction/UTransactor/UTransBuffer), Unreal serializes entire UObjects into the buffer and updates the Editor interface after Undo/Redo.
Doing a Undo/Redo at editor time can sometimes take up to 1second depending on the size of the blueprint. Which introduces a nother problem: We are developing for VR, so we have 11ms per frame, maybe 1ms at max for Undo/Redo operation.
We also want to release for standalone VR (Oculus Quest), where we face the problem of reduced memory and thus want to keep the items as small as possible.
Best thing I can think of is: stay with the Command Design Pattern:
- Items only contain the data they need -> Small memory footprint
- Do only what needs to be done (no overhead) -> Fast execution
Still facing the problem with deleted runtime created objects that are referenced in the UndoRedo buffer.
And also problems like a slider in an interface: the slider influences a value and we want to save that value to the buffer. But when do you save it? the slider updates the value continually and saving to the buffer every time the value changed is overkill. Basically you only want to save the value after the player released the slider. That again requires the user to assign to the event of slider got released for every slider (head spinning just thinking about the upcomming bug mess). And interface interaction also breaks the principle of the UndoRedo item executes the action.
Any thoughts on that?