Jump to content
UnitySpain

Aceptamos donaciones vía Paypal.

UnitySpain.com es un servicio gratuito, pero mantener la Comunidad conlleva una serie de gastos.

Fondo Anual Unityspain: Donados 58,34€ de 150,00€

  • Servidor: Dominio.com y Hosting Web
  • Mantenimiento de los Foros
  • Contenido y Servicios Extras
  • Mantenimiento para Redes Sociales
Sign in to follow this  
ftejada

Mostrar variables de un scriptableObject en un custom editor

Recommended Posts

Hola a todos!!

estoy intentando que se muestren las variables publicas que tengo en una clase que hereda de ScriptableObject en un custom Editor que estoy haciendo

[System.Serializable]
public class ClaseA : ScriptableObject
{
	public bool showShapes        = true; 
}


public class MainClass : Monobehaviour
{
	//public ClaseA claseA = new ClaseA(); //Tambien probé a poner esto en vez de la linea de abajo pero no solucionaba el problema
	public ClaseA claseA; 
}


[CustomEditor(typeof(MainClass))]
public class MainClassEditor : Editor
{
	SerializedProperty claseA = null;

	OnEnable()
	{
		claseA = serializedObject.FindProperty("claseA");
	}

	public override void OnInspectorGUI()
	{
		//....

		EditorGUILayout.PropertyField(claseA, true);	//¿Supuestamente con true como segundo parametro dibuja las variables que tenga esta property?
	
		//...
	}
}

El caso es que no se porqué no se muestran las variables, solo se muestra el campo para asignar/arrastrar el ScriptableObject en cuestion. Si no hay ninguno asignado entiendo que no se muestre nada, pero una vez asignado... no se pq.

Cuando quiero mostrar arrays de clases con todas sus variables publicas lo hago con serializedObject.FindProperty(property.GetArrayElementAtIndex(i), true) y me muestra todas sus variables publicas poniendo en true el segundo parametro de la funcion FindProperty(). 

Acaso no se pueden mostrar las variables de un scriptableObject mediante FindProperty(property, true);?????

He estado buscando por internet y la documentacion durante varias horas pero no he podido encontrar por que me ocurre este problema.

Version de Unity 2018.2.0

 

Gracias por adelantado. Un saludo

Edited by ftejada

Share this post


Link to post
Share on other sites


Por si te sirve, si no comenta y buscamos alguna solución, pero el tema de los Scriptable Objects lo tengo un poco oxidado jajajaja

Share this post


Link to post
Share on other sites

A ver, ese código es un poco como un potaje. Son conceptos diferentes mezclados. Te explico:

- Un SO ya es serializable, con lo cual ese [System.Serializable] sobra.

- No requieres ni de MonoBehaviour ni del Editor para mostrar los datos

En base sería:

 

	[System.Serializable]
    public class soItem {
       	public string title;
        public string desc;
	}

	[CreateAssetMenu(menuName = "SOComponents/Items")]
    public class soSoyUnSO : ScriptableObject {
		[SerializeField] private List<soItem> _items = new List<soItem>();		
          
      private void OnEnable() {
            Debug.Log("OnEnable");
        }

        private void OnDisable() {
            Debug.Log("OnDisable");
        }          
	}

El CreateAssetMenu te creará una opción en el menú contextual de proyecto para añadirlo a una carpeta.

La class soItem contiene los datos. Es una clase pura.

La class soSouyunSO es el SO para mostrarlos.

Te puedes crear una función en el SO para añadirlos por code a la lista o desde el editor a mano.

 

Share this post


Link to post
Share on other sites
5 hours ago, ftejada said:

El caso es que no se porqué no se muestran las variables, solo se muestra el campo para asignar/arrastrar el ScriptableObject en cuestion. Si no hay ninguno asignado entiendo que no se muestre nada, pero una vez asignado... no se pq.

Que se muestren las variables significa que el editor del SCO se visualize en otro editor? por ej en un asset mio (Kinematic 2D) tengo lo siguiente:

SCOEditor.jpg

Fijate que el SCO (con sus campos serializables) se muestran en cada editor del componente Character Hybrid Brain, pero en realidad corresponden a un nuevo editor (anidado).

Por ej, el primero que aparece ("Input Data") tiene el siguiente código:

...

//El campo del objeto, el SCO
EditorGUILayout.PropertyField( inputData );  

            GUILayout.Space(10);

            
			//Si no es nulo dibujarlo
            if( inputData.objectReferenceValue != null )
            {
                GUILayout.BeginVertical( EditorStyles.helpBox );
				
				// inputEditor es de tipo "Editor", si es nulo crealo
                if( inputEditor == null )
					//Crear el editor
                    CreateCachedEditor( inputData.objectReferenceValue , null , ref inputEditor );
                
				//Ejecutar OnInspectorGUI del editor creado (OnInspectorGUI dentro de OnInspectorGUI --> anidado)
                inputEditor.OnInspectorGUI();

                GUILayout.EndVertical();
            }
            else
            {
				
                if( inputEditor != null )
                    inputEditor = null;
                
                EditorGUILayout.HelpBox( "Select a Character Input Data asset" , MessageType.Warning );
            }

 

5 hours ago, ftejada said:

Acaso no se pueden mostrar las variables de un scriptableObject mediante FindProperty(property, true);?????

Para buscar las variables de un scriptable object vas a tener que generar un serializedObject a partir del objecto (scriptableObject.objectReferenceValue):

sObject = new SerializedObject(scriptableObject.ObjectReferenceValue);

una vez creado podés buscar las propiedades:

SerializedProperty property = sObject.FindProperty("property");

 

No se si puse los nombres exactamente como son, pero se entiende.

 

En Resumen:

  • Para acceder a un scriptableObject necesitas crearlo, el serializedObject que normalmente llamas es el correspondiente al monobehaviour, no al scriptableObject que te interesa
  • Unity utiliza editores anidados casi siempre, fijate el PostProccesingStack, la mayor parte corresponde a mini editores que se van dibujando con OnInspectorGUI, obviamente todos ScriptableObject
  • Los ScriptableObject son completamente serializables, podés anidar los que quieras, funcionan muy bien para representar SCO abstractos (abstract class ...) donde dibujas sin conocer el tipo derivado final (esto no es posible con clases de C# serializadas, otra vez, el ejemplo del PPStack sirve de ejemplo)
Edited by lightbug

Share this post


Link to post
Share on other sites
On 7/26/2019 at 5:24 PM, lightbug said:

Que se muestren las variables significa que el editor del SCO se visualize en otro editor? por ej en un asset mio (Kinematic 2D) tengo lo siguiente:

SCOEditor.jpg

Fijate que el SCO (con sus campos serializables) se muestran en cada editor del componente Character Hybrid Brain, pero en realidad corresponden a un nuevo editor (anidado).

Por ej, el primero que aparece ("Input Data") tiene el siguiente código:


...

//El campo del objeto, el SCO
EditorGUILayout.PropertyField( inputData );  

            GUILayout.Space(10);

            
			//Si no es nulo dibujarlo
            if( inputData.objectReferenceValue != null )
            {
                GUILayout.BeginVertical( EditorStyles.helpBox );
				
				// inputEditor es de tipo "Editor", si es nulo crealo
                if( inputEditor == null )
					//Crear el editor
                    CreateCachedEditor( inputData.objectReferenceValue , null , ref inputEditor );
                
				//Ejecutar OnInspectorGUI del editor creado (OnInspectorGUI dentro de OnInspectorGUI --> anidado)
                inputEditor.OnInspectorGUI();

                GUILayout.EndVertical();
            }
            else
            {
				
                if( inputEditor != null )
                    inputEditor = null;
                
                EditorGUILayout.HelpBox( "Select a Character Input Data asset" , MessageType.Warning );
            }

 

Para buscar las variables de un scriptable object vas a tener que generar un serializedObject a partir del objecto (scriptableObject.objectReferenceValue):


sObject = new SerializedObject(scriptableObject.ObjectReferenceValue);

una vez creado podés buscar las propiedades:


SerializedProperty property = sObject.FindProperty("property");

 

No se si puse los nombres exactamente como son, pero se entiende.

 

En Resumen:

  • Para acceder a un scriptableObject necesitas crearlo, el serializedObject que normalmente llamas es el correspondiente al monobehaviour, no al scriptableObject que te interesa
  • Unity utiliza editores anidados casi siempre, fijate el PostProccesingStack, la mayor parte corresponde a mini editores que se van dibujando con OnInspectorGUI, obviamente todos ScriptableObject
  • Los ScriptableObject son completamente serializables, podés anidar los que quieras, funcionan muy bien para representar SCO abstractos (abstract class ...) donde dibujas sin conocer el tipo derivado final (esto no es posible con clases de C# serializadas, otra vez, el ejemplo del PPStack sirve de ejemplo)

Gracias a todos por responder. Hay algunas cositas que aun no veo claro...

@lightbug inputEditor de donde sale?  qué almacena exactamente? Perdona la torpeza pero no lo termino de entender.

@iRobb

On 7/26/2019 at 12:48 PM, iRobb said:

- Un SO ya es serializable, con lo cual ese [System.Serializable] sobra. 

Gracias por la info sobre esto. No terminaba de entender realmente si me servia en un SO. Ya todo claro

Por otra parte, se que de la manera que indicas no necesito mostrar ni cambiar los valores de las variables del SO desde un "custom Inspector" por llamarlo de algun modo.

Aunque en el ejemplo que puse en codigo simplifique todo para que se entendiese el problema, en realidad tengo muchos SO con muchas opciones que el usuario debe configurar. Por eso necesito que todo se pueda manejar desde un solo sitio "centralizado", en vez de tener que obligar al usuario a buscar los SO, en sus respectivas carpetas del proyecto, cada vez que quiera modificar alguna configuracion.

Por eso pensé y creo que la mejor manera es mediante un CunstomInspector que maneje todos los SO y sus variables para poderse mostrar y configurar desde ahí. Si no he entendido lo que querias decirme ruego me disculpes.

Saludos

Share this post


Link to post
Share on other sites
11 minutes ago, ftejada said:

Gracias a todos por responder. Hay algunas cositas que aun no veo claro...

@lightbug inputEditor de donde sale?  qué almacena exactamente? Perdona la torpeza pero no lo termino de entender.

@iRobb

Gracias por la info sobre esto. No terminaba de entender realmente si me servia en un SO. Ya todo claro

Por otra parte, se que de la manera que indicas no necesito mostrar ni cambiar los valores de las variables del SO desde un "custom Inspector" por llamarlo de algun modo.

Aunque en el ejemplo que puse en codigo simplifique todo para que se entendiese el problema, en realidad tengo muchos SO con muchas opciones que el usuario debe configurar. Por eso necesito que todo se pueda manejar desde un solo sitio "centralizado", en vez de tener que obligar al usuario a buscar los SO, en sus respectivas carpetas del proyecto, cada vez que quiera modificar alguna configuracion.

Por eso pensé y creo que la mejor manera es mediante un CunstomInspector que maneje todos los SO y sus variables para poderse mostrar y configurar desde ahí. Si no he entendido lo que querias decirme ruego me disculpes.

Saludos

Disculpado aunque no hay ningún problema.

Y la opción de crear una class pura en cada componente que necesita de configuración, y luego las unificas todas en un solo SO? Sería algo así como:

public class componente : MonoBehavour {
	public class configComponente {
		dato, dato
	}
  
  [SerializeField] private soAll soAll;
  private configComponente configComponente;
  	
  	void Start() {
      configComponente = soAll.configComponente;
      dato = configComponente.dato;
    }

}

public class soAll : ScriptableObject {
  [SerializeField] private componente.configComponente _configComponente;

  public configComponente configComponente { get => _configComponente }
}

 

Share this post


Link to post
Share on other sites
On 7/26/2019 at 5:24 PM, lightbug said:

esto no es posible con clases de C# serializadas, otra vez, el ejemplo del PPStack sirve de ejemplo

Efectivamente, ahora mismo eso no es posible con clases C# serializadas, pero la buena noticia es que a partir de Unity 2019.3 lo va a ser gracias a un nuevo atributo llamado SerializeReference. Esto es algo que los que desarrollamos herramientas llevábamos AÑOS esperando que Unity implementase, así que hay cierta expectación con el tema.

Más información aquí: https://forum.unity.com/threads/serializereference-attribute.678868/

Share this post


Link to post
Share on other sites
On 7/28/2019 at 12:44 PM, xeleh said:

Efectivamente, ahora mismo eso no es posible con clases C# serializadas, pero la buena noticia es que a partir de Unity 2019.3 lo va a ser gracias a un nuevo atributo llamado SerializeReference. Esto es algo que los que desarrollamos herramientas llevábamos AÑOS esperando que Unity implementase, así que hay cierta expectación con el tema.

Más información aquí: https://forum.unity.com/threads/serializereference-attribute.678868/

Buenísimo, buena info.

 

On 7/28/2019 at 10:52 AM, ftejada said:

Gracias a todos por responder. Hay algunas cositas que aun no veo claro...

@lightbug inputEditor de donde sale?  qué almacena exactamente? Perdona la torpeza pero no lo termino de entender.

Ah perdon, inputEditor es un Editor, al igual que los editores que tenés en los inspectores, vos podés definir un Editor ( inputEditor ) y dibujarlo manualmente ( inputEditor.OnInspectorGUI() ).

En mi código está definido así:

Editor inputEditor = null;

En mi ejemplo tengo un editor por cada tipo de SCO, pero vos podés asignar todo a uno mismo, probablemente vas a tener que redibujarlo cada vez.

Edited by lightbug

Share this post


Link to post
Share on other sites

Gracias por las respuestas. Y parece que me va quedando algo mas claro todo este asunto... Voy a seguir con ello y si tengo alguna otra duda pregunto. Un saludo a todos.

Share this post


Link to post
Share on other sites
Sign in to follow this  

×
×
  • Create New...