How to make an undo redo system in runtime for GameObjects?


I’m implementing a VR app where I have objects like cubes, prisms, and spheres around the scene. I can move, scale and rotate them in runtime using the controller pointer and some UI elements.
I’m trying to make two UI buttons: one for undoing the latest action and another one for redoing the next action, in case there is one. For example, if I have a prism and I rotate it, and then I move the sphere to another place, if I press the undo button I want to set the sphere at the point it was before I moved it, and if I press undo another time, the prism will rotate as it was before I touched it.

I don’t know how to implement this behavior. I suppose I need a List but I don’t know how many, or if I need more than one or none at all.

I tried one thing and failed: I have a List of GameObjects where I store each shape I change in some kind of way, and I was expecting to destroy the latest GameObject in that array and instantiate the next one in case I press the undo button. The problem is that if I destroy a GameObject, the one in the List also destroys. I was thinking about having a Serializable with the properties of the shapes I have but I don’t know how to reference shapes, knowing the latest actions, the previous states… I’m kind of lost here.

If someone knows how to make this AT RUNTIME (not in the Editor), I would appreciate an explanation about what data structure you recommend and how to make the impression of delete a shape and other one appears. I don’t need literally code but some kind of guidance on how to achieve this behavior.

Thank you so much and I hope I explained myself well.

i would use a custom class that holds everything about the state of your shape that can be changed.
and use that class in a list. this a basic example to get you started but you would pry want to add color, size and whatever else.

also Dont Destroy your gameobects… toggle whether they are active in the scene or not. then you can refer back to them when they are “gone”.

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

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) {

	void Start () {
		UndoList = new List<setting> ();


Each interaction you do with an object you should write to a Stack (similar to the list but more suitable for this kind of situation). Therefore you should create some class for it, name it “interaction” for example :wink: IThere can be some abstract class with a couple of methods or an interface. Then you have specific classes for different types of interactions, for example, translateInteraction, scaleInteraction, rotateInteraction, changeColorInteraction and so on. They all have a method called “Undo” for example, plus some state to which they should return, this state is registered before interaction occurs (there is an interaction manager or something, who trigger saving the state for each interaction). You can store interaction stack inside the interaction manager for all interactions or separately for each object to manipulate depending on your need. Again, each time you interact with an object, the interaction manager creates new interaction instance object of a given type and store it into the stack, once you activate “undo” function, you pop the last element from the stack and use it for undo. If you use the single stack for all objects in the scene, your interaction records should also have a pointer to the object for which to apply the undo. Hope this will not confuse you more than help :slight_smile: