Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

425
Views
Unity3D muestra un UnityEvent correctamente en una lista reordenable

Estoy tratando de hacer un inspector personalizado para mi clase de secuencia. La idea es permitir que el usuario configure varios UnityEvents que se llaman al principio o al final de una secuencia.

Quiero tener una colección de secuencias en ReorderableList para que sea altamente configurable dentro del inspector.

Estoy muy cerca de una solución, pero no tengo experiencia con las secuencias de comandos del editor. Mis scripts casi funcionan correctamente. Pero todavía necesito resolver la mejor manera de ajustar dinámicamente la altura vertical de cada elemento, en el método DrawListItem, y la altura vertical total en el método ElementHeight.

Estoy considerando tratar de deserializar los eventos de la unidad para poder usar el método GetPersistentEventCount para tener una idea de la altura vertical requerida, pero parece que esto probablemente sea excesivo. Sospecho que debe haber una forma más sencilla de recuperar estos datos.

Actualmente, cuando agrego varios elementos a la secuencia, obtengo lo que se muestra a continuación, donde los campos de eventos se superponen entre sí y los botones Agregar/Quitar están debajo del Evento de Unity inferior.

¿Alguien sabe la mejor manera de resolver esto?

ingrese la descripción de la imagen aquí

 using UnityEngine; using UnityEditor; using UnityEditorInternal; using System; using UnityEngine.Events; [CustomEditor(typeof(SequenceManager))] public class SequenceManagerEditor : Editor { SerializedProperty Sequences; ReorderableList list; private void OnEnable() { Sequences = serializedObject.FindProperty("Sequences"); list = new ReorderableList(serializedObject, Sequences, true, true, true, true); list.drawElementCallback = DrawListItems; list.drawHeaderCallback = DrawHeader; list.elementHeightCallback = ElementHeight; } //Draws the elements in the list void DrawListItems(Rect rect, int index, bool isActive, bool isFocused) { SerializedProperty element = list.serializedProperty.GetArrayElementAtIndex(index); ////NAME EditorGUI.LabelField(new Rect( rect.x, rect.y + EditorGUIUtility.standardVerticalSpacing, 50, EditorGUIUtility.singleLineHeight), "Name"); EditorGUI.PropertyField( new Rect( rect.x + 50, rect.y + EditorGUIUtility.standardVerticalSpacing, rect.width - 50, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("Name"), GUIContent.none ); //ON INIT EditorGUI.LabelField(new Rect( rect.x, rect.y + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing * 3, 50, EditorGUIUtility.singleLineHeight), "OnInit"); EditorGUI.PropertyField(new Rect( rect.x + 50, rect.y + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing * 3, rect.width - 50, 3 * rect.y + 5 * EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("OnInit"), GUIContent.none); //ON DONE EditorGUI.LabelField(new Rect( rect.x, rect.y + 7 * EditorGUIUtility.singleLineHeight, 50, EditorGUIUtility.singleLineHeight), "OnDone"); EditorGUI.PropertyField( new Rect( rect.x + 50, rect.y + 7 * EditorGUIUtility.singleLineHeight, rect.width - 50, 3 * rect.y + 12 * EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("OnDone"), GUIContent.none); SerializedProperty indexProperty = element.FindPropertyRelative("index"); indexProperty.intValue = index; } private float ElementHeight(int index) { return (13 * EditorGUIUtility.singleLineHeight); } //Draws the header void DrawHeader(Rect rect) { string name = "Sequences"; EditorGUI.LabelField(rect, name); } public override void OnInspectorGUI() { //base.OnInspectorGUI(); serializedObject.Update(); this.list.DoLayoutList(); serializedObject.ApplyModifiedProperties(); } }

en aras de la exhaustividad, también he agregado la clase Sequence y la clase SequenceManager a continuación.

 using UnityEngine; using UnityEditor; using System; using UnityEngine.Events; [Serializable] public class Sequence { public string Name; public UnityEvent OnInit; public UnityEvent OnDone; private Module _module; public int index; private bool active; //Called By The Sequence Manager At the start of a sequence internal void Init(Module p_module) { Debug.Log($"sequence: {Name} with index: {index} has started"); active = true; _module = p_module; if(OnInit.HasNoListners()) { Done(); } else { OnInit.Invoke(); } } //Called Manually to Trigger the End of the Sequence internal void Done() { if (!OnDone.HasNoListners()) { OnDone.Invoke(); } active = false; Debug.Log($"sequence: {Name} with index: {index} is done"); _module.FinishedSequence(index); } //Check if active internal bool GetActive() { return active; } }
 using System; namespace UnityEngine { [Serializable] public class SequenceManager: MonoBehaviour { #region Properties public Sequence[] Sequences; #endregion } }
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Es posible acceder a los campos públicos de Sequence emitiendo los elementos de serializedObject.targetObjects en la secuencia de comandos de su editor. También puede usar serializedObject.targetObject o Editor.target si no está usando [CanEditMultipleObjects] .

 if(target is not SequenceManager manager) { //target was not a SequenceManager, the manager variable will be null return; }

y dentro de ElementHeight() :

 var sequence = manager.Sequences[index]; var size = sequence.OnInit.GetPersistentEventCount() + sequence.OnDone.GetPersistentEventCount();

Editar : después de probar algunas cosas, aprendí que puede obtener el tamaño de la matriz a través de la propiedad serializada. Puedes usar esto en ElementHeight() :

 var element = list.serializedProperty.GetArrayElementAtIndex(index); var size = element.FindPropertyRelative("OnInit.m_PersistentCalls.m_Calls").arraySize + element.FindPropertyRelative("OnDone.m_PersistentCalls.m_Calls").arraySize;
over 4 years ago · Santiago Trujillo Report

0

En lugar de una altura de elemento predeterminada codificada de

 X * EditorGUIUtility.singleLineHeight

debería usar EditorUtility.GetPropertyHeight y obtener la altura real de las propiedades como

 private float ElementHeight(int index) { var property = list.serializedProperty.GetArrayElementAtIndex(index); return EditorUtility.GetPropertyHeight(property); }

Esto devuelve la altura que la propiedad requeriría usando su cajón de propiedades predeterminado, el que se aplica usando PropertyField , lo cual hace;)


Además de eso: ¿Cuál es exactamente el propósito de su editor personalizado?

Desde Unity 2020, el cajón predeterminado para listas y matrices es ReorderableList de todos modos, así que para ser honesto, realmente no veo que su editor personalizado agregue nada que no sea el Inspector predeterminado de todos modos :)

Así es como se ve sin su editor personalizado:

ingrese la descripción de la imagen aquí

Si prefiere cambiar la forma en que se dibuja una Sequence en el Inspector en general, sería mejor implementar un PropertyDrawer personalizado y no tener que lidiar con la lista en absoluto.

¡Y el cajón que maneja el index es por cierto peligroso/no confiable!

Actualmente, su índice solo se aplica si está realmente abierto en el Inspector y no en el modo de depuración. ¿Qué pasa si luego quieres modificar esto a través de un script?

En mi opinión, sería mejor si su SequenceManager simplemente pasara el índice al método Init si realmente se necesita para algo que no sea el registro;)


También tenga mucho cuidado: en su Sequence comandos tiene

 using UnityEditor;

tenga en cuenta que este espacio de nombres solo está disponible dentro del propio editor de Unity y se elimina por completo durante la compilación.

=> Desea asegurarse de que nada de este espacio de nombres esté tratando de usarse en una aplicación creada, por lo que tendrá que envolver cualquier referencia a este espacio de nombres en las etiquetas de preprocesador correspondientes, como por ejemplo

 #if UNITY_EDITOR using UnityEditor; #endif

y lo mismo para cualquier código relacionado con este espacio de nombres (consulte también Compilación dependiente de la plataforma )

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!