[Solved] Destroy instantiated prefabs with a same tag, one by one, from last instantiated to first ?
Hello all,
I am trying to destroy instantiated prefabs with a same tag, one by one, from last instantiated to first, and I am stuck on how to accomplish this.
The idea is that I want to have a custom editor, which would allow me to instantiate multiple prefabs and then "undo" the last instantiation with two GUI buttons - "Place object" and "Undo", respectively.
As of now, I am able to successfully instantiate prefabs, add the same tag to them, and then destroy them one by one, but they are getting destroyed from first to last instantiated.
The code I have so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectInstantiateControl : MonoBehaviour {
public List<GameObject> prefabList = new List<GameObject>();
[HideInInspector]
public int objectSelectionIndex = 0;
GameObject instance;
public void PlaceObject()
{
switch (objectSelectionIndex)
{
case 1:
Debug.Log("Just received a number 1 from the editor");
GameObject object_A = Resources.Load("Object_A") as GameObject;
instance = Instantiate(object_A, this.transform.position, this.transform.rotation, this.transform);
instance.tag = "UsedObject";
prefabList.Add(instance);
break;
case 2:
Debug.Log("Just received a number 2 from the editor");
GameObject object_B = Resources.Load("Object_B") as GameObject;
instance = Instantiate(object_B, this.transform.position, this.transform.rotation, this.transform);
instance.tag = "UsedObject";
prefabList.Add(instance);
break;
case 3:
Debug.Log("Just received a number 3 from the editor");
GameObject object_C = Resources.Load("Object_C") as GameObject;
instance = Instantiate(object_C, this.transform.position, this.transform.rotation, this.transform);
instance.tag = "UsedObject";
prefabList.Add(instance);
break;
case 4:
Debug.Log("Just received a number 4 from the editor, deleting the object");
prefabList.Remove(GameObject.FindWithTag("UsedObject"));
DestroyImmediate(GameObject.FindWithTag("UsedObject"));
break;
}
}
}
And the part from the editor script for GUI buttons "Place object" and "Undo" :
GUILayout.BeginHorizontal();
if (GUILayout.Button("Place object", GUILayout.Height(25)))
{
ObjectInstantiateControl myScript = (ObjectInstantiateControl)target;
myScript.objectSelectionIndex = 1;
myScript.PlaceObject()();
}
if (GUILayout.Button("Undo", GUILayout.Height(25)))
{
ObjectInstantiateControl myScript = (ObjectInstantiateControl)target;
myScript.objectSelectionIndex = 4;
myScript.PlaceObject();
}
GUILayout.EndHorizontal();
Any ideas or suggestions are welcome. Thanks in advance ;)
Answer by LiloE · Feb 22, 2017 at 12:09 PM
Use a Stack to manage undo
A Stack is a last-in-first-out structure. Use it like this:
Stack<GameObject> undoStack = new Stack<GameObject>();
// whenever you instantiate a new object, push it to the stack
undoStack.Push(theObject);
// on undo, just pop the last one and destroy it.
var objToUndo = undoStack.Pop();
Destroy(objToUndo ); // tip: avoid using DestroyImmediate. It's better to disable the object before destroying it if you must have it disappear immediately.
Thanks LiloE, that is exactly what I was looking for!
However, when trying to first disable and then Destroy(objToUndo), the object gets disabled but not destroyed, and I get the message "Destroy may not be called from edit mode! Use DestroyImmediate ins$$anonymous$$d.", while using DestroyImmediate works like a charm.
One more thing, is there a way to avoid the InvalidOperationException: Operation is not valid due to the current state of the object System.Collections.Generic.Stack message once there are no more gameObjects in the stack and the "Undo" button is clicked?
Thanks again!
EDIT: No worries, I was trying so hard to overthink it, when I realized that a simple IF statement will do the trick!
if (undoStack.Count > 0)
{
GameObject objToUndo = undoStack.Pop();
DestroyImmediate(objToUndo);
}
Answer by Zee-Play · Feb 22, 2017 at 04:52 AM
I would create a Gameobject list and destroy the last gameobject in the list every time you press undo.
Look for game object list here on answers, should find the solution you need.