- Home /
Problem is not reproducible or outdated
How to store, change and delete gameobject and it's list element?
So, i'm making a plugin to create/modify/delete gameobjects using custom editor with custom classes list. Everything seems to work fine, but sometimes when i try to remove a class from list(including referenced gameobject which is created on scene), editor gives me an error "Out of range exception". I hope, that somebody can help me out! :) Cheers! :) P.S Here's my source code: Data script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class PresentationMaker : MonoBehaviour
{
//Slide data class
[System.Serializable]
public class Slide
{
public GameObject Object;
public int AnInt;
public float AnFloat;
public Vector3 AnVector3;
public Vector3[] AnIntArray = new Vector3[0];
public bool ExpItem = false;
public bool Instantiated = false;
}
//List for slide data class
public List<Slide> SlideList = new List<Slide>(1);
void AddNew()
{
SlideList.Add(new Slide());
}
void Remove(int i)
{
SlideList.RemoveAt(i);
}
}
Editor script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
using UnityEditor.SceneManagement;
[InitializeOnLoad]
public static class ToggleItem
{
const string toggleName = "Presentation Maker/Options/Show warning before delete";
static bool enabled_;
static ToggleItem()
{
ToggleItem.enabled_ = EditorPrefs.GetBool(ToggleItem.toggleName, false);
EditorApplication.delayCall += () =>
{
PerformAction(ToggleItem.enabled_);
};
}
[MenuItem(ToggleItem.toggleName)]
static void ToggleAction()
{
PerformAction(!ToggleItem.enabled_);
}
public static void PerformAction(bool enabled)
{
Menu.SetChecked(ToggleItem.toggleName, enabled);
EditorPrefs.SetBool(ToggleItem.toggleName, enabled);
ToggleItem.enabled_ = enabled;
PresentationMakerEditor.swbd = enabled;
Debug.Log(PresentationMakerEditor.swbd);
}
}
[CustomEditor(typeof(PresentationMaker))]
[CanEditMultipleObjects]
public class PresentationMakerEditor : Editor
{
PresentationMaker PM;
SerializedObject SerObj;
SerializedProperty SerProp;
public List<GameObject> SlidesGOs;
int ListSize;
public static bool swbd;
static string ln = "_______________________________________", pmn = "PresentationManager";
string InitObjPath = "Prefabs/DefaultSlide";
[MenuItem("Presentation Maker/Create Manager")]
static void CreateMaker()
{
if (GameObject.FindGameObjectWithTag(pmn) != null)
Debug.LogWarning("Presentation manager already exists!");
else
{
Instantiate(Resources.Load("Prefabs/" + pmn), Vector3.zero, Quaternion.identity);
GameObject.FindGameObjectWithTag(pmn).name = pmn;
}
}
void OnEnable()
{
PM = (PresentationMaker)target;
SerObj = new SerializedObject(PM);
SerProp = SerObj.FindProperty("SlideList"); // Find the list in script and create a reference
SlidesGOs = new List<GameObject>();
}
public override void OnInspectorGUI()
{
SerObj.Update();//Update list
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Define slides quantity with a number");
ListSize = SerProp.arraySize;
ListSize = EditorGUILayout.IntField("List size", ListSize);
if (ListSize != SerProp.arraySize)
{
while (ListSize > SerProp.arraySize)
{
SerProp.InsertArrayElementAtIndex(SerProp.arraySize);
}
while (ListSize < SerProp.arraySize)
{
SerProp.DeleteArrayElementAtIndex(SerProp.arraySize - 1);
}
}
EditorGUILayout.Space();
//Or add a new item to the List<> with a button
EditorGUILayout.LabelField("Add a new slide with a button");
if (GUILayout.Button("Add a new slide"))
{
PM.SlideList.Add(new PresentationMaker.Slide());
}
EditorGUILayout.Space();
EditorGUILayout.Space();
if (GUILayout.Button("Remove all"))
{
if (swbd)
{
if (EditorUtility.DisplayDialog("Warning!", "Are you sure you want to delete all slides?", "Yes", "No"))
{
ListSize = 0;
SerProp.arraySize = 0;
}
}
else
{
ListSize = 0;
SerProp.arraySize = 0;
}
}
//Display the list to the inspector window
for (int i = 0; i < SerProp.arraySize; i++)
{
SerializedProperty SlideListRef = SerProp.GetArrayElementAtIndex(i);
SerializedProperty Obj = SlideListRef.FindPropertyRelative("Object");
SerializedProperty MyInt = SlideListRef.FindPropertyRelative("AnInt");
SerializedProperty MyFloat = SlideListRef.FindPropertyRelative("AnFloat");
SerializedProperty MyVect3 = SlideListRef.FindPropertyRelative("AnVector3");
SerializedProperty MyArray = SlideListRef.FindPropertyRelative("AnIntArray");
SerializedProperty _ExpItem = SlideListRef.FindPropertyRelative("ExpItem");
SerializedProperty _Instantiated = SlideListRef.FindPropertyRelative("Instantiated");
// Hide class instance's values inside foldout
_ExpItem.boolValue = EditorGUILayout.Foldout(_ExpItem.boolValue, i.ToString() + " slide", true);
if (_ExpItem.boolValue)
{
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("Automatic Field By Property Type");
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(Obj);
if (EditorGUI.EndChangeCheck() || PrefabUtility.GetPrefabObject(Obj.objectReferenceValue) != null)
{
InitObj(_Instantiated, Obj, InitObjPath, i, true);
}
if (_Instantiated.boolValue == false || Obj.objectReferenceValue == null)
{
InitObj(_Instantiated, Obj, InitObjPath, i, false);
}
EditorGUILayout.PropertyField(MyInt);
EditorGUILayout.PropertyField(MyFloat);
EditorGUILayout.PropertyField(MyVect3);
// Positions array
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Array Fields");
if (GUILayout.Button("Add New Index", GUILayout.MaxWidth(130), GUILayout.MaxHeight(20)))
{
MyArray.InsertArrayElementAtIndex(MyArray.arraySize);
MyArray.GetArrayElementAtIndex(MyArray.arraySize - 1).vector3Value = new Vector3(0, 0, 0);
}
for (int n = 0; n < MyArray.arraySize; n++)
{
EditorGUILayout.PropertyField(MyArray.GetArrayElementAtIndex(n));
if (GUILayout.Button("Remove (" + n.ToString() + ")", GUILayout.MaxWidth(100), GUILayout.MaxHeight(15)))
{
MyArray.DeleteArrayElementAtIndex(n);
}
}
EditorGUILayout.Space();
//Remove this index from the List
EditorGUILayout.LabelField("Remove an index from the List<> with a button");
if (i >= 0 && i <= SlidesGOs.Count)
{
if (GUILayout.Button("Remove This Index (" + i.ToString() + ")"))
{
if (swbd)
{
if (EditorUtility.DisplayDialog("Warning!", "Are you sure you want to delete the slide?", "Yes", "No"))
{
SerProp.DeleteArrayElementAtIndex(i);
SlidesGOs.Remove(SlidesGOs[i].gameObject);
DestroyImmediate(SlidesGOs[i].gameObject);
SlidesGOs.RemoveAt(i);
}
}
else
{
SerProp.DeleteArrayElementAtIndex(i);
DestroyImmediate(SlidesGOs[i]);
SlidesGOs.RemoveAt(i);
}
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
EditorGUILayout.Space();
}
}
if (GUI.changed)
SetObjDirty(PM.gameObject);
SerObj.ApplyModifiedProperties();
}
public static void SetObjDirty(GameObject obj)
{
EditorUtility.SetDirty(obj);
EditorSceneManager.MarkSceneDirty(obj.scene);
}
public void InitObj(SerializedProperty SerPropBool, SerializedProperty SerPropObj, string ObjPath, int index, bool Changed)
{
GameObject TempObj;
SerPropBool.boolValue = true;
Debug.Log("created");
if (Changed)
{
DestroyImmediate(SlidesGOs[index].gameObject);
SlidesGOs.RemoveAt(index);
TempObj = (GameObject)Instantiate(SerPropObj.objectReferenceValue, Vector3.zero, Quaternion.identity);
SlidesGOs.Insert(index, TempObj);
}
else
{
TempObj = (GameObject)Instantiate(Resources.Load(ObjPath), Vector3.zero, Quaternion.identity);
SlidesGOs.Add(TempObj);
}
SerPropObj.objectReferenceValue = TempObj;
}
}
Follow this Question
Related Questions
C# GameObject Lists 2 Answers
How to add a reorderable list on CUSTOM EDITOR WINDOW? 0 Answers
Removing GameObjects from list (with List.Remove()) doesn't seem to be removing them 2 Answers
How to add and remove objects from a list when they get destroyed and instantiated 0 Answers
A node in a childnode? 1 Answer