EditorGUILayout.EnumPopup shows always the same selected option but works as programmed
Hello everyone. I am building an editor script that let me chose which component add to a game object. In this case i want to use a drop down menu as i want only one choice available at time. The gameobject can have only one compoment among the ones into the drop down list. I used EnumPopup to do what i want and it works, except that the selection field shows always the same name. What i expect: click on drop down menu, list of available choice shows, click on the component that i want to add, add component and the menu selection stay visible into the popup field. What i obtain: the same as above except that the enum popup field shows always the same selection despite it add the right component that i chose.
My Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using System;
enum componentEnum
{
Component1,
Component2,
Component3,
Component4,
Component5,
Component6,
Component7,
ComponentDefault
};
[CustomEditor(typeof(Initializer))]
public class InitializerEditor : Editor
{
interactorEnum interactor = interactorEnum.ObjectInteractor;
public override void OnInspectorGUI()
{
DrawDefaultInspector();
Initializer script = (Initializer)target;
popupComponents(script.gameObject);
}
void popupComponents(GameObject targetObject)
{
EditorGUI.BeginChangeCheck();
{
interactor = (interactorEnum)EditorGUILayout.EnumPopup("Primitive to create:", interactor);
if (EditorGUI.EndChangeCheck())
{
InstantiateComponent(interactor, targetObject);
}
}
}
void InstantiateInteractor(interactorEnum interactor, GameObject targetObject)
{
switch (interactor)
{
case interactorEnum.Component1:
addInteractor<Component1>(targetObject);
break;
case interactorEnum.Component2:
addInteractor<Component2>(targetObject);
break;
case interactorEnum.Component3:
addInteractor<Component3>(targetObject);
break;
case interactorEnum.Component4:
addInteractor<Component4>(targetObject);
break;
case interactorEnum.Component5:
addInteractor<Component5>(targetObject);
break;
case interactorEnum.Component6:
addInteractor<Component6>(targetObject);
break;
case interactorEnum.Component7:
addInteractor<Component7>(targetObject);
break;
default:
addInteractor<ComponentDefault>(targetObject);
break;
}
}
void addInteractor<T>(GameObject targetObject)
where T : Component
{
T component = null;
bool hasInteractor = targetObject.TryGetComponent<ComponentDefault>(out ObjectInteractor cd);
if (hasInteractor)
{
bool hadComponent = targetObject.TryGetComponent(out component);
if (!hadComponent)
{
DestroyImmediate(cd);
component = targetObject.AddComponent<T>();
}
}
else
{
component = targetObject.AddComponent<T>();
}
}
}
Can someone explain to me why the selection from the menu list doesn't stay selected into the field? Can you explaint to me where i am doing wrong, please?
Answer by Hellium · Oct 04, 2021 at 12:58 PM
using UnityEngine;
using UnityEditor;
using System;
[CustomEditor(typeof(Initializer))]
public class InitializerEditor : Editor
{
// We suppose here that all the types derive from Component
// Change the components to whatever you need
private static readonly Type[] types = new Type[]
{
typeof(MeshRenderer),
typeof(MeshFilter),
typeof(BoxCollider)
};
private static string[] options;
private void OnEnable()
{
options = Array.ConvertAll(types, t => t.Name);
}
public override void OnInspectorGUI()
{
DrawDefaultInspector();
Initializer script = (Initializer)target;
DrawComponentsPopup(script.gameObject);
}
private void DrawComponentsPopup(GameObject targetObject)
{
EditorGUI.BeginChangeCheck();
{
int oldTypeIndex = GetExistingComponentIndex(targetObject, out Component component);
int typeIndex = EditorGUILayout.Popup("Component", oldTypeIndex, options);
if (EditorGUI.EndChangeCheck())
{
if (oldTypeIndex >= 0)
DestroyImmediate(component);
if (typeIndex >= 0)
targetObject.AddComponent(types[typeIndex]);
}
}
}
private int GetExistingComponentIndex(GameObject targetObject, out Component component)
{
Component c = null;
int index = Array.FindIndex(types, t => targetObject.TryGetComponent(t, out c));
component = c;
return index;
}
}
Hello @Hellium your solutions works, but i don't understand why $$anonymous$$e isn't working ad i want. The two solution do the exact same things except to what is shown in the popup field after the selection. The only difference between $$anonymous$$e and your code (not considering EnumPopup and Popup) is that you before the EndChangeCheck use the old index inside popup method. Can you explain the reasons behind this 2 differente behaviours please?
To be honest, I did not even tried to understand the code you've provided in the question.
However, what I suspect (and what I had to solve in my code) is that your interactor
gets reset to its original value when a component is added or removed.