Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Ampliando el Editor y la madre que lo hizo.

Iniciado por Tizon, Abril 02, 2017, 08:25:56 PM

Tema anterior - Siguiente tema
Buenas, vuelvo nuevamente con un montón de dudas, la mayoría seguramente tontas, pero llevo una semana y pico trasteando con el tema y me parece que cada vez más perdido.
 
Para ponernos en situación, tras que @GSG3D me descubrieran esa maravilla del ScriptableObject, que se adaptaba como un guante a mis necesidades, he puesto codos en el tema, y he rehecho mi proyecto. El caso es que es sencillo, intuitivo y funciona fantástico como base de datos, lo hace todo de maravilla. Ahora bien, al emplearlo como base de datos, tiene un problema, y es que al manejarlo desde el inspector, para que nos hagamos a la idea, tengo una clase que referencia a otra clase, y esta a otra y esta a una colección de otras clases y así, con lo cual a la hora de establecer las referencias en el inspector es un caos de desplegables y datos que es muy difícil ir siguiendo.
 
Bueno, así que empiezo a buscar por dónde puedo racionalizar la edición de toda esta información. Y aquí es dónde empiezo a liarme como un trompo. Bien, primer paso lógico, la documentación oficial. Ahí me encuentro con la posibilidad de crear Property Drawers. Sobre la claseA puedes crear:
 
[CustomPropertyDrawer (ClaseA)]
 
class ClaseADrawer : PropertyDrawer {}
 
Bien, hasta aquí bien. El caso en que no he conseguido encontrar en ningún lado que digan dónde se ha de meter el dichoso script para poder jugar con él. Digo yo que será en la carpeta editor, pero no me funciona. En la clase original? También he probado y me ha tirado muchos errores. Seguro que algo hago mal, pero no puedo saberlo a ciencia cierta si de buen inicio no sé dónde se mete.
 
Por otro lado, investigando esto, doy con la posibilidad de crear tu propia ventana del editor, Bien, estupendo. La verdad es que encuentro información muy buena y es sencillo de hacer. Ahora bien, a la hora de dotarlo de contenido... Ahí nuevamente no me salgo. Pienso hacer una ventana con tres secciones en vertical, la de la izquierda, tendrá unos botones de arriba a abajo con los diferentes tipos de clases que tiene mi proyecto. La idea es que al pulsar el botón de una determinada clase, se listen todas las instancias con sus propiedades y referencias, como en el editor (Y con sus Property Drawers cuando consiga hacerlo) y que al hacer clic sobre una referencia se listen todas las instancias del tipo de la referencia en el panel de más a la derecha, para poder seleccionarlas con un simple clic. Consigo dividirlo en tres con la propiedad BeginArea y EndArea y queda bien. Pero al insertar el BeginArea dentro del if(GuiButton) como dicen en la documentación me desaparece y temo que es porqué la crea como un subarea dentro del primer área. En fin, que voy más perdido que un bacalao en el Sahara. Si alguien pudiera echar un poco de luz, me diga si voy bien encarado o estoy confundiendo cosas, o conoce algún tutorial que vaya un poco más allá de simplemente poner un botoncito y alguna cosa más, algo más elaborado, estaría muy agradecido.

Hola, es mucho lo que tenes que referenciar? la idea es que con cada SCO hagas referencias a assets y recursos, valores y esas cosas, no me queda muy en claro porque mencionas los de las multiples referencias que haces. Si podrias dar un ejemplo estaria mejor.
 
 
 
Cita de: Tizon date=1491157556Pero al insertar el BeginArea dentro del if(GuiButton) como dicen en la documentación me desaparece y temo que es porqué la crea como un subarea dentro del primer área
   


lo pusiste dentro del GUI.button ? osea la funcion esa se pone en true solo cuando presionas sobre el botón, es util para llamar a metodos mas que nada o realizar acciones de una sola vez ... en teoria el area apareceria y desapareceria, si lo que queres es activar/desactivar usa "toogle": Por ej:
 

unaBool = GUILayout.Toggle (unaBool, "Una Bool", "Button");   // el "Button es para que se vea como un boton"

 
Asi manejandote con flags (bool's) podes de entrada dibujar todo lo que tengas que dibujar, y antes de hacerlo verificar si el flag correspondiente esta en true, un ejemplito:
 

flagArea1 = GUILayout.Toggle (flagArea1, "Area 1", "Button");
if(flagArea1)
{
beginArea Area1

Dibujar Area1
endArea Area1
}
flagArea2 = GUILayout.Toggle (flagArea2, "Area 2", "Button");   
if(flagArea2)
{
beginArea Area2

Dibujar Area2
endArea Area2
}

 
 

No se si te servirá, pero para guardar depende de que cosa puedes usar un solo script. Yo tengo una clase estática que he llamado GameData en la que voy guardando referencias que me sirven para diferentes scripts, después desde cada script solo tengo que acceder a GameData y buscar la información. Así no tienes que estar guardando lo mismo en diferentes scripts. 
 
Yo tampoco acabo de entender la relación con los Scriptable Objects, cómo los estas utilizando? Yo los uso para items, armas y cosas así, y en uno de los scripts tengo arrays con cada grupo de SCO, si necesito información de uno voy al array que toca y lo busco.

Hola,
 
@TheBullet yo lo hago servir al revés, es decir, de Game Data y de ahí es de dónde voy creando los objetos. En tu caso tendrás algo similar a esto.
 
Pero encuentro que es estupendo para crear ya en él las relaciones e interacciones. Por ejemplo, yo tengo:
 

 
Y como puedes ver ya creo las relaciones directamente en tiempo de diseño.
 

 
Con lo cual aparte de crear las clases directamente desde aquí, ya veo como se van linkando las relaciones en tiempo de diseño, con lo que veo los errores rápido, aparte de que una vez consiga crear la herramienta, puede ser un editor de escenas o de niveles rápidisimo. El problema viene cuando tienes muchas clases ya linkadas. Te encuentras con un pastel como este:
 

 
Como puedes ver, se ha perdido toda la facilidad de seguir y comprobar con un vistazo y de generar rápido relaciones, escenarios y/o niveles. Quizá es un poco deformación profesional. Hacía años que no programaba. Tras años de programar en C++, hace años que lo más cercano que he hecho es el diseño y administración de bases de datos, con lo cual lo concibo como tal y lo diseño del mismo modo y es la función que me viene como anillo al dedo, ya que así es como me encuentro como pez en el agua.
 
Aún me faltan por averiguar cosas, como si los cambios en las clases se reflejan en el ScriptableObject en tiempo de ejecución (Vamos, si es lectura/escritura o sólo lectura) o si puedo hacerlo servir como SaveGame, o si caerá mucho el rendimiento cuando le meta chicha de verdad, pero vamos, que son cosas que trasteando iré averiguando, el caso ahora mismo es conseguir racionalizarlo para poder seguir trasteando y hacer pruebas y ver hasta dónde se puede llegar.
 
 
 
@lightbug Bueno, lo hice así por qué así lo había visto en varios sitios. De ahí había sacado la conclusión de que el área era persistente hasta que se sobreescribía, ya que de otro modo no le encontraba sentido. Ya me extrañaba que de ser persistente no hubiera modo fácil de referenciarlo.
 
Bueno, como serán varios, un toogle exactamente no, quiza un SelectionGrid o algo similar se adaptara más. Pero me lo anoto y en cuanto pueda lo pruebo, Gracias, ya veo que era un concepto erróneo una vez más.
 
Puedes ver un ejemplo en la respuesta al compañero, justo arriba de este post.
 
Por un casual no sabrás dónde se han de poner los Scripts con los PropertyDrawer? Si es así ya te invito a una cerveza o a lo que quieras!!! 

Abril 03, 2017, 07:07:10 PM #4 Ultima modificación: Abril 03, 2017, 07:20:21 PM por TheBullet
Entonces tienes todos los datos en un solo Scriptable Object? Yo no lo utilizo de esta manera, por ejemplo, para cada arma tengo un archivo con los datos de esa arma y cada vez que tengo que crear una nueva arma voy a Assets>Create>Arma y un nuevo archivo se crea para configurar la nueva arma. 
 
Por ejemplo, para lo que tu me enseñas yo tendría:

- Para cada Sistema Solar un SCO, con su ID, posición y número de planetas. 

- Los planetas los podría guardar dentro del SCO de su sistema solar o tener SCO para los planetas y vincularlos con el sistema solar por id.

- Cada mercado con un SCO, con su ID y el ID de los elementos que puede vender. Si los mercados no tienen nombre (como me parece ver), puedes reutilizar mercados en varios planetas para no tener tanto follón de datos.

- Cada tipo de item para vender un SCO para no tener que repetir los datos como el nombre del producto en cada mercado que se venda. Para variar el precio, yo pondría en estos SCO un precio medio, y por código haría que fluctuara el precio y así te evitas tener que poner todos los precios a mano.
 
Todo esto ordenado por carpetas claro.
 
No se como es tu juego, pero si hay muchos planetas y mercados, quizás lo mejor sería crear un código que decidiera los productos, la cantidad y los precios que se venden en cada mercado, si lo hicieras así no necesitarías ni los SCO de los mercados, solo los de los items a vender e indicar el número de mercados en cada planeta.
 
Yo en tu caso lo habría hecho de esta manera, quizás no es la mejor y otros foreros te indican una mejor manera, pero yo creo que sería menos liosa y tendrías que poner menos datos.
 
Diría que los SCO no están pensados para utilizarlos para guardar partida, seguro que se podrá hacer (aunque no se si es buena idea).
 
Espero que te haya dado ideas. Saludos!
 
 
 
 
 
Por cierto, se me olvidaba.
 
Yo utilizo ID en los SCO para identificarlos cuando guardo y cargo partida, pero si utilizas los archivos de la forma que te he dicho no hacen falta los ID para vincularlos. Por ejemplo, yo tengo una clase de SCO que se llaman Atributo. Esta clase son características de los capitanes de las naves y dan bonificaciones o penalizaciones, cada atributo tiene su contrario, por ejemplo "Veterano" es contrario a "Novato". Como necesito identificar los contrarios para que nunca se apliquen a la vez, en estos SCO tengo un array donde meto los Atributos contrarios a ese. Tu puedes hacer lo mismo para vincular sistemas solares, planetas, mercados etc., de esta forma puedes vincular SCO sin tener que utilizar IDs y es mucho más visual, los IDs te irán bien para guardar datos pero para vincularlos entre si mejor hacerlo directamente.

- los SCO se pueden usar para guardar datos (nunca lo he hecho pero he leido que se ha usado asi), pero no fueron hechos para tal proposito y hay muchas otras formas mas eficientes y prolijas de hacerlo. JSON me encanta para esto, sobre todo con JSONUtility que incorporo unity desde 5.3.
 
- para mi el enfoque correcto es el que te dice @TheBullet , si necesitas un planeta creas un SCO planeta, y asi. Si necesitas que un SCO sea accesible desde todos lados podes incluso hacerlo un singleton, para mi es mejor que una clase estatica ya que te aseguras que siempre exista uno solo. Por ejemplo tenes tu SCO mercadoCentral (singleton) y tu carpeta llena de mercados (SCO's) y cada mercado con sus productos (SCO's). Podes decir que el mercadoCentral busque todos los SCO "mercados" y los guarde en su lista, entonces te liberas de usar los Propertydrawers ya que el proceso de creacion pasa en el mismo editor y no lo haces "todo de una" en un mismo SCO. O colocas el mercadoCentral como un gameObject con sus mercados referenciados, como desees.
 
- Si queres asegurarte al 100% que cada elemento tenga un unico id usa el mismo numero de posicion en la Lista/array, supongo que ahi los estas eligiendo vos, si tuvieras 500 elementos y le erraste en un id te la vas a queres cortar ;)
 
Cita de: Tizon date=1491236962Por un casual no sabrás dónde se han de poner los Scripts con los PropertyDrawer? Si es así ya te invito a una cerveza o a lo que quieras!!! 
   


Jaja los propertyDrawer nunca los he usado, pero cuando los abris bajo que assemblys aparecen en el arbol del proyecto? si aparecen bajo Editor supongo que los pondria en la carpeta "Editor".
 
saludos

Los SCO van muy bien para crear plantillas o prefabs de Scripts (así como los Prefabs son para GameObjects...), porque permiten establecer unos datos por defecto, admiten métodos y funciones, y todo queda guardado físicamente como archivo dentro del Proyecto.
 
Si vas a querer guardar o salvar datos luego, sirven de doble propósito como Clase 'bypass', como container de los datos que necesites guardar, para que no tengas que volver a crear la estructura de nuevo...
 
 

Hola, perdón por el retraso en la respuesta, pero quería probar antes de hablar. Cosas de ser programador dominguero.
 
@lightbug Tenías razón, van en la carpeta editor. Simplemente estaba haciendo algo mal.
 

 
Ahora es cuestión de ir explorando hasta dónde se puede llegar y que cosas se pueden hacer.
 
Para lo de dividir la ventana la idea y la corrección de los conceptos equivocados que tenía también me ha venido muy bien.
 

 
Al final he usado SelectionGrid. La verdad es que ha sido un poco complicado, por qué la documentación es algo escasa (o no he sabido encontrar la adecuada) y resulta que aunque le pasas el índice como parámetro, sino igualas antes, siempre te da como defecto el botón de inicio y no te deja cambiar, con lo cual, por mucho que pulses botones siempre está el mismo. Paso el código por si a alguien más le pasa, antes de volverse loco con esa chorrada como me pasó a mí.
 
    int m_selGridInt = 0;

    string[] m_selStrings = new string[] { "Puro Item Comercio", "Puro Item Carga", "Puro Item Mercado" };
 
    m_selGridInt = GUILayout.SelectionGrid(m_selGridInt, m_selStrings, 1);
 
Por lo demás, he encontrado una página que explica como dividir la ventana en paneles. Aún no he podido verla con detenimiento, pero pienso hacerlo en cuanto pueda. La adjunto por si a alguien le resulta de interés.
 
http://gram.gs/gramlog/creating-editor-windows-in-unity/
 
Nuevamente, @pioj gracias por vuestra ayuda y vuestras respuestas.
 
 

Esto tambien me vino bien a mi, hace poco me cruce con un problema en una ventana y necesitaba usar una selectionGrid que antes ni conocia.

@Tizon Ahora el listado de items se ve mucho más claro! Aunque sigo pensando que es un error no usar SCO para cada elemento, cuando tengas que utilizar traducciones, equilibrar los precios a nivel general o simplemente asignar una imagen a cada tipo elemento tendrás problemas y te llevará mucho tiempo...
 
Saludos!

Etiquetas: