14 diciembre 2025

Análisis del libro "Game Design Workshop" de Tracy Fullerton

Portada del libroHay muchas maneras de entrar en el desarrollo de videojuegos. Todos lo hacemos desde nuestro placer por jugar, pero unos tenemos un trasfondo técnico y entramos directamente a programar con un engine, otros se meten después de hacer sus pinitos en el mundo del modding o de la creación de niveles para un juego específico y otros incluso se meten desde el mundo de los juegos físicos en tablero. 

Este libro es para todos ellos porque parte del concepto más abstracto de lo que llamamos juego y, si bien lo acaba concretando en un videojuego, se centra en el proceso creativo de generar ideas, encontrar las más prometedoras, probarlas con un prototipo que no tiene por qué ser como su forma final, iniciar un proceso iterativo de refinado hasta dar con algo genuinamente divertido por su concepto en sí (y no por su implementación) y, sólo entonces, empezar su desarrollo. Y es que el libro no empieza a tratar lo que conocemos por desarrollo hasta su tercer tercio, e incluso entonces no trata la parte técnica del desarrollo, en este libro no se ve ni una línea de código, sino su parte de planificación y gestión de la labor de un grupos de personas.

El libro adopta el punto de vista del diseñador de videojuegos. Si bien es un rol muy específico dentro de un grupo de desarrollo de videojuegos, se trata del que tiene un papel más transversal, como el libro se encarga de explicar, y por tanto cuenta con más visibilidad de todo el proceso, de ahí su importancia.

Los dos primeros tercios del libro se encargan de explicar el rol del diseñador de videojuegos; qué entendemos por juego; cuales son sus elementos fundamentales; qué elementos los enriquecen para darles el carácter que queremos; cuales son las dinámicas de juego más habituales según ese carácter; cómo podemos mantener el interés de los jugadores conforme pasa el tiempo; y cómo podemos mantener el juego equilibrado para evitar la frustración del jugador o, peor, su aburrimiento. Luego pasa a cómo filtrar y refinar las ideas de juegos que tengamos, dándole muchísima importancia (y capítulos) al proceso de prototipado y prueba de esos prototipos con jugadores reales (al margen del diseñador). Prueba del enfoque eminentemente "meta" del libro es la insistencia del libro en que los prototipos probados empiecen siendo físicos, en papel y cartón incluso, desde mucho antes de hacer el primer prototipo digital. Ese enfoque de evitar los prototipos digitales, hasta muy avanzado el proceso, puede resultar chocante para los que disfrutamos escribiendo líneas de código, pero el autor se encarga de razonar dicho enfoque de una manera muy convincente y realmente refrescante.

El último tercio es el que trata el desarrollo propiamente dicho, pero con un enfoque "alejado del teclado". Aquí, el libro trata de ponerte en la piel de un gestor de equipo que tiene que coordinar a multiples especialistas para dar forma a un juego que se pueda vender. Todo el libro tiene un enfoque muy realista, pero aquí es donde más se nota. El autor hace un esfuerzo notable en transmitirte el día a día de un estudio de desarrollo de videojuegos, tanto en sus labores internas cotidianas de creación del juego, como en sus interacciones con actores externos clave para su prueba, financiación y distribución, como son los testers o las casas publicadoras (publishers). Para ello, te explica cómo estructurar los equipos de desarrollo, qué roles son los habituales y cómo se puede relacionar entre sí de una manera eficiente y sana. Luego te explica cómo pueden ayudar las metodologías ágiles a humanizar el desarrollo y mejorar su producto. Me ha gustado mucho cómo te explica el funcionamiento del mercado del videojuego y te mentaliza sobre cómo aproximarte a una publicadora para que esta elija tu juego para financiarlo. Llega incluso a hablar sobre cómo suelen ser los contratos típicos entre publicadoras y equipos de desarrollo, para que entiendas cómo funciona el sistema de pago por hitos durante el desarrollo, y luego el posterior de royalties tras la publicación del juego. Es un interesantísimo baño de realidad, que sirve para desmitificar el mundo del desarrollo del videojuego, pero al mismo tiempo da una medida del enorme esfuerzo que hay detrás de un juego que consigue venderse.

Todo lo anterior ya tiene un valor enorme, pero además el libro está aderezado con los testimonios de muchos diseñadores de juegos. Te encontrarás con que más de uno habrá hecho juegos que hayas disfrutado. En esos testimonios, cada uno de ellos te cuenta cómo se introdujo en el mundillo del diseño y desarrollos de videojuegos, que es lo que les atrae de él y cual es el proceso creativo que siguen a la hora de darle forma a un juego. Leerlos, humaniza el papel del diseñador, pone rostro a las personas que están detrás de los juegos que más has disfrutado y te permite conocer el camino vital que han seguido hasta llegar al punto de poder crear los juegos que les han hecho famosos. Muchos de esos caminos vitales no han sido fáciles. Más de uno llega al punto de recomendarte que no te metas en el mundillo si tienes vocación o pasión clara, ya que no es una profesión fácil ni que te haga rico. Pero todos ellos confirman que si realmente quieres hacer juegos, y estás dispuesto a hacer el esfuerzo y los sacrificios, se trata de una profesión que puede llenarte plenamente.

Por tanto, si no sólo te gustan los juegos, sino como se hace, este es tu libro. Es un refrescante baño de realidad, que desmitifica, humaniza y reivindica el esfuerzo creativo que hay detrás de lo que disfrutas en to PC o consola. Un  libro realmente recomendable.

07 diciembre 2025

Serialización de diccionarios en Unity

En desarrollo, la serialización consiste cambiar el formato de un objeto de memoria para que pueda ser almacenado en disco. 

Uno de los formatos más populares de serialización es JSON, un estándar de texto con el que guardas datos en ficheros siguiendo una estructura de llaves muy similar a la de los diccionarios de Python. 

Cuando serializas un objeto, la instancia de una clase, a JSON lo que haces es seleccionar los datos claves del objeto y los conviertes en campos y valores de un fichero JSON. ¿Cuáles son los datos claves del objeto? es el mínimo subconjunto de datos que te permita reconstruir el objeto en el estado que necesitas. Ese proceso de reconstrucción es lo que se denomina deserialización y es el inverso al otro: lees el fichero y con su contenido creas una instancia de la clase con un estado lo más parecido posible al original.

Unity está constantemente serializando y deserializando. Cuando usamos el inspector para darle valor a un campo público de un MonoBehavior, Unity serializa ese valor a su propio formato para que lo tengas en el inspector la próxima vez que arranques el editor. Por defecto, Unity hace ese proceso con todos los campos públicos de los MonoBehaviour y los ScriptableObject, pero también puedes forzarlo en los campos privados si los defines precedidos del atributo [SerializeField]. Ese tributo tiene también el efecto de permitirnos editar en el inspector campos privados. Sin él, el inspector sólo muestra los públicos. Cuidado, eso no significa que tengas que usar ese atributo en todos los campos privados de tu MonoBehavior. Su uso sólo tiene sentido en aquellos campos que contienen valores de base de tu clase, es decir, aquellos que configurarías en el inspector antes de la ejecución del juego. Preceder un campo calculado de con [SerializeField] no tendría sentido, salvo que quisieras conservar ese valor calculado para una ejecución posterior.

Precisamente, ese era el caso que me movió a escribir este artículo. Estoy escribiendo una clase que me permita analizar un escenario y generar un grafo representando todas sus zonas transitables. El proceso de creación del grafo no viene a cuento, pero mi era que el grafo se generase en tiempo de desarrollo, se guardase y se cargase en tiempo de ejecución. Vamos, que quería que mi grafo se guardase en un ScriptableObject. Uno de los componentes de mi grafo se basa en un diccionario, cuyas claves son las coordenadas enteras de una malla rectangular, y sus valores los nodos con los enlaces a los nodos vecinos. Y el problema viene porque Unity no sabe serializar diccionarios. Puede serializar listas, pero no diccionarios. Ese es el motivo por el que puedes editar listas en el inspector, pero no diccionarios.

Los diccionarios son una de las estructuras de datos más comunes en desarrollo, así que no he sido el primero en encontrarse este problema. Es tan habitual, que otros engines, como Godot, llevan a gala poder serializar diccionarios.

¿Cómo se puede sortear ese problema? Bueno, puedes generar una clase que represente hacia fuera el comportamiento de un diccionario, pero que por dentro se base en dos listas, una de claves y otra de valores. A la hora de serializar, se guardarían esas dos listas que sí que son procesables por Unity. A la hora de deserializar, se leerían esas dos listas y se usarían para crear en memoria un diccionario interno desde el que la clase ofrecería su funcionalidad al resto de los componentes del juego. Esta solución es perfectamente legítima, pero a estas alturas ha sido tan usada que ya ha sido incluida en una herramienta de serialización de múltiples tipos de clases (no sólo diccionarios) como es Odin Serializer. Así que sería como reinventar la rueda. Si con todo y con eso, quieres hacértelo tú mismo, la misma página de Odin te explica cómo, aunque advierte de que el demonio está en los detalles y que puede haber situaciones raras al editar prefabs que pueden obligar sofisticar bastante la implementación inicial. Ese camino ya lo han recorrido los chicos de Odin Serializer, así que voy a explicar cómo utilizarlo.

Logo de Odin Serializer
Logo de Odin Serializer

Odin Serializer es una herramienta open source y gratuita. Te la puedes descargar de su página web, en formato de paquete de unity con todos los ficheros de código fuente para serializar todo lo que permite Odin. Odin Serializer es sólo el banderín de enganche gratuito de un conjunto de herramientas que, esas sí, son de pago. A partir del serializador gratuito abarcan una herramienta para crear inspectores personalizados y otra para encontrar errores en tus proyectos. Ambas son potentísimas. La primera te permite ahorrarte el paso por el UI Toolkit a la hora de implementar inspectores cómodos y eficientes. La segunda detecta los errores más típicos en el desarrollo con Unity y ofrece un conjunto de atributos personalizados para cargar de semántica tus campos y detectar casos en los que sus valores no se ajustes a su semántica (o directamente impedirte introducir esos valores). Aunque en el caso concreto de este artículo me ha bastado con usar el Serializer gratuito, te recomiendo que le eches un ojo a sus otras herramientas y precios. Son de pago único y de una cuantía tirada para un desarrollador indie.

La página de descarga sólo te pide el namespace base de tu juego, para personalizar los namespaces de todos los ficheros de código incluidos. El paquete incluye una carpeta OdinSerializer de la que cuelgan el resto de carpetas de la herramienta. Tienes que colocar esa carpeta dentro de la de Scripts de tu juego.

Una vez importado en tu carpeta de Scripts, OdinSerializer ofrece un conjunto de clases especializadas que heredan de las habituales en Unity:

  • SerializedBehaviour
  • SerializedComponent
  • SerializedMonoBehaviour
  • SerializedNetworkBehaviour
  • SerializedScriptableObject
  • SerializedStateMachineBehaviour
  • SerializedUnityObject

Te basta con sustituir la clase de Unity de la que herede tu componente por la equivalente para que Odin se encargue de serializar aquellos tipos de los que Unity no se ocupe. Todos los diccionarios, por ejemplo, serán serializados por Odin sin que haga falta nada más, de manera que si editas su contenido desde el editor, se conservará entre ejecuciones de este.

Sin embargo, hay que tener en cuenta que aunque serialices el contenido del diccionario con Odin, el inspector de Unity será incapaz de leerlo. Así que no te extrañe si tu diccionario público sigue sin aparecer en el inspector. Para eso haría falta instalarse Odin Inspector, que es uno de los componentes de pago. Sin ese componente, cualquier modificación desde el editor del contenido de un diccionario serializado debería venir de scripts personalizados para ejecutarse desde el editor. Mi caso era precisamente ese, ya que he configurado un botón en el inspector del componente de mi grafo para generar la malla al pulsarlo y guardar los valores creados en el diccionario interno del componente. Si modifico el escenario, no tengo más que volver a pulsar el botón para regenerar la malla del grafo.

Con Odin Serializer deberías ser capaz de resolver la mayor parte de tus necesidades para serializar diccionarios, pero no siempre es tan sencillo. Aunque ya había usado Odin Serializer en proyectos más simples, no he conseguido hacerlo funcionar en el proyecto que motivó este artículo. Generaba mi grafo correctamente al pulsar el botón, pero dicho grafo no estaba allí en el siguiente arranque del editor o al recargar el nivel. Por lo que quiera que sea, el diccionario que contenía el grafo no se salvaba al guardar el nivel. Le he dado muchas vueltas y no sé si se debe a que tengo varios niveles de diccionarios anidados unos dentro de otros, o porque los scripts que contienen esos diccionarios están colocados en prefabs también anidados. También puede ser porque mi componente usa un editor personalizado, lo que añade un nivel más de indirección a la serialización de sus datos. Sea por la razón que sea, al final no me ha quedado más remedio que implementar mi propia serialización. Precisamente esa serialización manual acerca de la que prevenía, si podías resolver tu problema con Odin. En esta ocasión no me ha quedado más remedio que reinventar la rueda, aunque he tenido la suerte de poder contar con el método explicado en la misma página de Odin Serializer. Te voy a contar cómo, por si te sirve para salir del paso en alguna ocasión.

Como decía antes, la clave está en crear una clase que herede de Dictionary para conservar su funcionalidad. Para dotar a esa nueva clase de la capacidad de serializarse dentro de Unity, hay que hacer que implemente el interfaz ISerializationCallbackReceiver. Cuando Unity recibe la orden de serializar una clase, porque el campo de esa clase sea público o esté marcado con el atributo [SerializeField], espera que dicha clase implemente el interfaz ISerializationCallbackReceiver. Ese interfaz consta de dos métodos, OnBeforeSerialize() en el que deberemos implementar cómo queremos guardar la información de nuestro objeto al serializar, y OnAfterDeserialize() en el que implementaremos cómo recuperar la información guardada para reconstruir con ella el estado del objeto.

La clase que he creado se basa en dos listas, una para las claves del diccionario y otra para sus valores. Será en esas listas donde guarde los datos a conservar, gracias a que Unity sí que serializa listas de manera nativa.

Los campos de mi diccionario personalizable
Los campos de mi diccionario personalizable

Ahora la implementación del interfaz. Primero para el proceso de serialización.

Proceso de serialización de mi diccionario personalizable
Proceso de serialización de mi diccionario personalizable

Cuando Unity llame a OnBeforeSerialize() será porque es hora de guardar la información del estado del objeto. Para ello, lo que hago es vaciar el contenido anterior de las listas (líneas 42 y 43) para volver a rellenarlas con el listado actualizado de las claves y los valores del diccionario. Cuando se cierre la instancia de la clase se perderá el contenido del diccionario, pero las listas habrán quedado serializadas junto con el resto de información de la escena.

Ahora el proceso inverso. Se abre de nuevo la escena y Unity llama a los métodos OnAfterDeserialize() de todos sus objetos para que estos restauren su estado anterior a partir de la información deserializada.

Proceso de deserialización de mi diccionario personalizable
Proceso de deserialización de mi diccionario personalizable

Como se puede ver en el listado, dado que las listas sí que serializaron, estarán con su contenido intacto al llamar a OnAfterDeserialize() lo que permitirá utilizarlo para restaurar las entradas del diccionario. En la línea 34 a 36 se puede ver que recorro ambas listas para regenerar las entradas del diccionario interno de la clase.

Ahora viene algo importante. Unity no puede serializar tipos genéricos y la clase recién creada (UnitySerializedDictionary) lo es. La solución es concretar la clase genérica para cada uno de los usos a los que la apliquemos. Una vez concretada, la clase resultante sí podrá ser serializada por Unity. Esa es la razón por la que tengo un fichero aparte, estático, con las diferentes versiones concretadas del diccionario genérico.

Clases concretas a partir de la genérica
Clases concretas a partir de la genérica

Para evitar cualquier tentación de usar directamente la clase genérica, sin concretarla, lo mejor es marcarla como abstracta.

Serán esas versiones concretas las que podamos usar en nuestro código, con la tranquilidad de que Unity conservará su contenido entre ejecuciones.

Uso del diccionario concretado
Uso del diccionario concretado

MonoBehaviour que utiliza nuestro diccionario concretado y serializable
MonoBehaviour que utiliza nuestro diccionario concretado y serializable

Espero que te haya resultado útil y que te sirva para no cortarte a la hora de usar diccionarios en tus componentes.

26 octubre 2025

Implementación de una regla para medir distancias en escenarios de Unity

Por alguna razón que desconozco, Unity carece de una herramienta que permita medir distancias en los escenarios y prefabs. Godot sí que la tiene, pero Unity no, a pesar de que es muy útil tanto para construir tus escenarios como para evaluar tus pruebas de funcionalidad. Por ese motivo, el Unity Asset Store está repleta de assets que ofrecen esta funcionalidad... previo pago. Hace poco me vi en la necesidad de medir distancias en un proyecto de Unity en el que ando metido y me planteé comprar uno de estos assets, pero luego me lo pensé mejor. "No puede ser tan difícil de implementar por uno mismo", lo intenté y resultó ser sencillísimo. En este artículo te voy a explicar cómo. Primero lo que queremos conseguir y luego pasaremos a los detalles de implementación.

Una regla para medir distancias es conceptualmente sencilla. Se basa en dos variables independientes, una posición A y una posición B, cuya diferencia da lugar a la variable dependiente que queremos calcular, la distancia. Eso es lo mínimo. A partir de ahí, podemos añadir mejoras visuales o facilidades de manipulación. Para el ejemplo de este artículo quería una herramienta visual que pudiese mover por el escenario, con dos puntos de agarre para ajustar con el ratón las dos posiciones a medir.

La herramienta de medida a implementar
La herramienta de medida a implementar

También quería poder disponer de múltiples reglas simultáneamente, para poder desplegarlas por diferentes ubicaciones del escenario, siendo aquellas visibles en todo momento sin necesidad de que estuviesen seleccionadas. La apariencia visual de las reglas debía ser configurable para que pudieran resaltar adecuadamente en diferentes escenarios. Así que debía poder configurar el color de las líneas, su grosor, y las dimensiones de los extremos de la regla. Además la regla debía dar las posiciones globales de sus extremos para permitir un emplazamiento preciso. Con todas esas condiciones, lo que buscaba era que la regla tuviese un inspector como el de la figura siguiente.

Inspector de la herramienta
Inspector de la herramienta

Teniendo en cuenta todo lo anterior, podemos pasar a los detalles de implementación. Por cierto, todo el código que vamos a ver está recogido en el repositorio de GitHub de la herramienta. Allí se describe cómo instalar la herramienta cómodamente, usando el Package Manager de Unity. En otro articulo explicaré cómo he empaquetado la herramienta para que se pueda instalar desde el repositorio con el Package Manager.

Usando el repositorio como referencia, el primer fichero a explicar es el de Assets/Runtime/Scripts/MeasuringTape.cs. Este fichero es el componente MonoBehaviour que se montará sobre un Transform para ser instanciado en el escenario, y es el que contiene el modelo de datos de la herramienta. Este no puede ser más sencillo:

Assets/Runtime/Scripts/MeasuringTape.cs
Assets/Runtime/Scripts/MeasuringTape.cs


Los campos de las líneas 8 y 9 son las dos variables independientes de las que hablábamos antes, las posiciones de los puntos A y B. Es importante señalar que son posiciones relativas a la del GameObject sobre el que se monte este componente. Quería hacerlo así para tener la posibilidad de mover la regla por el escenario de una sola vez, sin necesidad de tener que desplazar primero un extremo y luego el otro. También es importante darle un valor por defecto, diferente de cero, a ambas posiciones. De otra manera, sus agarradera visuales coincidirán con la del Transform del GameObject y no podremos manipularlas.

El resto de campos se refieren a la configuración visual de la herramienta:

  • color: El color de las líneas de la regla.
  • thickness: El grosor de dichas líneas.
  • endWidth: La longitud de las líneas transversales de los extremos de la regla.
  • endAlignment: Un valor entre -1 y +1 para bascular las líneas transversales de los extremos a un lado o a otro de la regla. Es una opción interesante si queremos poner múltiples reglas en el escenario a modo de cotas.
  • textSize: Tamaño de la fuente utilizada para mostrar la distancia medida.
  • textDistance: Distancia a la regla del texto con la distancia medida. Puede recibir valores negativos, en cuyo caso el texto pasa a mostrarse por el otro lado de la regla.
Aparte de lo anterior, MeasuringTape.cs ofrece dos propiedades con la posición global de los extremos de la regla:

Assets/Runtime/Scripts/MeasuringTape.cs
Assets/Runtime/Scripts/MeasuringTape.cs

Para tener dos agarraderas visuales con las que fijar los valores de localPositionA y localPositionB, arrastrando el ratón, recurriremos a los Handles de Unity. Los Handles son controles visuales que responden a la interacción del usuario, como clicks, arrastres y rotaciones. Cada vez que mueves un objeto por la escena, lo haces manipulando el Handle que representa la posición del objeto.

Para mostrar Handles personalizados tienes que crear un script en la carpeta Editor con una clase que herede de UnityEditor.Editor. Esa clase debe estar decorada con la etiqueta [CustomEditor] para señalar a qué MonoBehavior asociar los Handles. En el caso de nuestro ejemplo, este script está en Assets/Editor/DrawMeasuringTape.cs.

Es muy importante resaltar que cualquier script como este, que utilice clases del namespace UnityEditor, debe ir forzosamente en una carpeta llamada Editor. Si metes el script directamente en la carpeta Scripts, junto a los MonoBehaviours, te será imposible compilar el juego. Hay gente que mete la carpeta Editor dentro de la de Scripts. Yo prefiero tenerlas bien separadas.

Assets/Editor/DrawMeasuringTape.cs
Assets/Editor/DrawMeasuringTape.cs

Fíjate en la línea 6. A la etiqueta [CustomEditor] hay que pasarle el tipo del MonoBehaviour al que se asocia. Es una manera de decirle al editor: "cada vez que te encuentres con un MonoBehaviour de este tipo represéntalo, en el inspector y en la escena, tal y como se define aquí".

Es importante destacar que he dejado este script dentro del namespace por defecto. No sé muy bien la razón, pero sin intentaba ponerle un namespace personalizado me fallaba el dibujado de Gizmos del método DrawTapeGizmos(), que veremos más adelante.

La configuración de Handles se hace en el método OnSceneGUI(), propio de la clase UnityEditor.Editor

Assets/Editor/DrawMeasuringTape.cs
Assets/Editor/DrawMeasuringTape.cs

La gestión de Handles dentro de OnSceneGUI() siempre tiene la misma estructura. De hecho, no sería descabellado guardarte una plantilla, porque siempre acabas haciendo lo mismo.

Empiezas recuperando una referencia al MonoBehaviour al que se asocian los Handles. En OnSceneGUI(), lo habitual es usar el campo target de UnitEditor.Editor. Ese campo tiene la referencia que buscamos, aunque hay que hacerle un cast (línea 160) para recuperar el tipo exacto. Esa referencia nos será muy útil para leer y fijar las propiedades y campos del MonoBehaviour original.

Luego, viene el segmento en el que muestras tus Handles y recuperas sus valores. Dicho segmento se inicia con una llamada a EditorGUI.BeginChangeCheck() (línea 162). Esa llamada sirve para detectar si el usuario ha modificado algún control de la interfaz del editor entre esta llamada y su correspondiente EditorGUI.EndChangeCheck() (línea 172). En caso de que esta última llamada detecte algún cambio en los controles del editor, se recuperan los valores de estos y se guardan en el MonoBehaviour original (líneas 176 y 177). Esos cambios se registran en el sistema de Undo/Redo con la llamada a Undo.RecordObject() (línea 175). Dicho método registra todos los cambios que se realicen sobre el objeto pasado como parámetro, a partir de la llamada. El texto del segundo parámetro sirve para identificar el cambio en el historial de estos.

Entre las líneas 165 y 170 es donde se produce la creación de los Handles. Los hay de muchos tipos, cada uno con su propia apariencia y forma de ser manipulado. Los que he usado aquí son los más sencillos. Los PositionHandle se limitan a presentar un eje de coordenadas que podemos desplazar por el escenario. En caso de moverse, el Handle devuelve la nueva posición que, en nuestro caso, se almacena en las variables positionAHandle (línea 165) y positionBHandle (línea 168). Esas variables son las que se utilizan para actualizar los campos del MonoBehaviour de origen (líneas 176 y 177).

En casos sencillos, es bastante habitual ver implementaciones que introducen la representación visual de los Gizmos del objeto en el mismo método OnSceneGUI(), generalmente después del bloque del método EditorGUI.EndChangeCheck(). Yo lo he hecho así a menudo, pero tiene un par de inconvenientes. El primero es que mezclas en el mismo método la gestión de los controles visuales del objeto y la de los Gizmos que lo representan, lo que alarga y complica la implementación del método. El segundo problema es que toda la representación visual que incluyas en ese método sólo se mostrará cuando el objeto de origen esté seleccionado. Esto último era lo que me resultó bloqueante, dado que quería que la representación de la regla permaneciese aunque tuviésemos seleccionado otro objeto.

La alternativa que he descubierto es la de decorar un método estático con el atributo [DrawGizmo]. Este atributo señala a un método como el responsable de dibujar los Gizmos de un objeto. Por un lado te permite concentrar en él toda la lógica de la representación visual, dejando OnSceneGUI() para la de la gestión de Handles; y por otro lado, en función de los parámetros que le pasemos al atributo podremos definir cuándo queremos que se muestren los Gizmos.

Assets/Editor/DrawMeasuringTape.cs

Assets/Editor/DrawMeasuringTape.cs
Assets/Editor/DrawMeasuringTape.cs

En el caso del ejemplo, como se puede ver en la línea 108, le he pasado al atributo los flags necesarios para que los Gizmos se muestren tanto cuando el Gizmo esté seleccionado, como cuando no lo esté.

Para dibujar los Gizmos, he utilizado las funciones de dibujado de la librería Handles. Aquí hay cierto solapamiento con lo que ofrece la librería Gizmos, con la que también podemos dibujar. La ventaja de Handles es que te permite seleccionar el grosor de la línea dibujada, mientras que Gizmos sólo te permite dibujar con un grosor de 1 pixel. Partiendo de lo anterior, el resto de las líneas del método son muy similares a cuando dibujamos con Gizmos. 

En la línea 112, fijos el color de las líneas a dibujar, mientras que en la 113 dibujo la línea entre los dos extremos de la herramienta de medida. Fíjate que el tercer parámetro que se le pasa al método DrawLine() es precisamente el grosor de la línea a dibujar.  

Para resaltar los extremos y sus agarraderas visuales, en la línea 116 y en la 121 dibujo una circunferencia alrededor de los extremos. Para rematar estos, he dibujado líneas perpendiculares a la principal. Si quisiese que mi regla se limitase a medir en escenarios de juegos 2D me habría conformado con calcular la perpendicular a la línea principal, pero como quiero poder usarla en entornos 3D hay que buscar que la líneas que crucen los extremos sean también perpendiculares a la dirección de enfoque de la cámara. De otra manera, podría haber momentos en los que la cámara se moviese y las líneas de los extremos desapareciesen por quedar longitudinales a la dirección de enfoque. Para calcular la perpendicular a dos vectores, se usa el producto cruzado, el cual calculo en la línea 133. Hecho eso, ese vector perpendicular me sirve para calcular la semilongitud de los extremos (línea 146) y para dibujar estos, incorporando la basculación de endAlignment (líneas 147 y 150).

El vector perpendicular también es muy útil para separar el texto de la línea principal, desde el centro de esta. Dicho centro se calcula en la línea 138 y desde él se calcula la separación en la línea 142. Una vez que tenemos la ubicación, dibujo el texto en la línea 143. El "F2" de la llamada a ToString() es para que la distancia se muestre con dos decimales.

En este punto, ya tengo una regla de medir cuyos extremos puedo manipular y que se dibuja de la forma que se muestra en la imagen que se muestra al comienzo del artículo. Queda por aclarar cómo he hecho para que el inspector muestre la posición global en campos de sólo lectura. Aunque el MonoBehavior MeasuringTape tenga dos propiedades que ofrecen la posición global de los extremos, Unity no puede mostrar en el inspector propiedades (es una pena porque Godot sí que puede hacerlo). Para mostrar esas propiedades, y que sean sólo de lectura, hay que recurrir a un inspector personalizado. Para hacerlo hay que crear una clase que herede de UnityEditor.Editor, precisamente como la que ya hemos usado para los Handles y la representación visual, pero para representar inspectores personalizados hay que usar el método CreateInspectorGUI().

Dicho método se basa en la lectura que se hace de los valores serializados de los campos del objeto original a representar en el inspector. Esos valores se le pasan a la clase a través de un campo llamado serializedObject. Lo que yo suelo hacer es usar el método OnEnable() para conseguir referencias a cada uno de los campos del objeto original.

Assets/Editor/DrawMeasuringTape.cs

Para conseguir cada una de las referencias hay que llamar al método serializedObject.FindProperty() y pasarle una cadena de texto con el nombre del campo del objeto original que nos interesa. Lo de usar una cadena de texto no me convence, porque es fácil equivocarse, pero es lo que hay.

Una vez obtenidas las referencias a los campos del objeto original, ya podemos usarlas en CreateInspectorGUI().

Assets/Editor/DrawMeasuringTape.cs
Assets/Editor/DrawMeasuringTape.cs
Assets/Editor/DrawMeasuringTape.cs

En la línea 38 se crea el panel donde se representarán todos los campos del inspector. No quería hacer grandes alardes con el orden de los campos, así que me he limitado a organizarlos en el layout clásico vertical.

¿Te acuerdas cuando en OnSceneGUI() conseguía una referencia al MonoBehavior original, usando el campo target? Bueno, puede que estés tentado a hacer lo mismo en este método, pero la documentación de Unity advierte contra ello y exige que en este método en concreto se use serializedObject.targetObject, tal y como se puede ver en la línea 47. No entiendo bien a qué se debe esta peculiaridad, pero he preferido obedecer y hacerlo como recomendaba la documentación, en vez de ir a contracorriente y encontrarme con problemas raros luego.

Como me vale la visualización por defecto que se hace de los dos primeros campos, los de las posiciones locales, me he limitado a crear dos campos por defecto y a poblarlos con los valores del objeto original (líneas 50 y 52). Luego, añadimos los campos al panel (líneas 51 y 53)

En mi caso particular, suelo usar inspectores personalizados cuando quiero mostrar u ocultar campos en función del valor de otro anterior (por ejemplo, un booleano). En esas situaciones, me gusta situar los campos variables (los que se pueden mostrar o no) sobre un panel aparte del principal. Ese panel aparte es el que creo en la línea 56 y añado al principal en la 57. Luego, en la línea 60, le pasamos ese panel al método UpdateGlobalPositionFields() para que se creen sobre él los campos de sólo lectura con las posiciones globales. En un momento, veremos cómo funciona por dentro UpdateGlobalPositionFields(), pero para no perder el hilo de CreateInspectorGUI(), antes vamos a acabar de ver cómo funciona. 

Una vez que añadidos los campos donde se mostrarán las posiciones globales, quiero que estos se mantengan actualizados. Para ello, he enlazado UpdatePositionFields() con los campos de las posiciones locales, para que se ejecute cada vez que cambien los valores de las posiciones locales (líneas 64 a 67). Esto tendrá como efecto la actualización de las posiciones globales. 

Como me vale con que el resto de campos muestren su visualización por defecto, me limito a añadir sus respectivos PropertyField al panel principal (líneas 70 a 75).

Fíjate en que CreateInspectorGUI() tiene que devolver el panel principal para que el editor pueda mostrarlo en el inspector. Es lo que hago en la línea 77.

Lo prometido es deuda, así que ahora vamos a ver qué ocurre dentro de UpdateGlobalPositionFields().

Assets/Editor/DrawMeasuringTape.cs
Assets/Editor/DrawMeasuringTape.cs

Recuerda que acabo de mencionar que a este método le paso como primer parámetro el subpanel en el que se dibujan los campos que queremos actualizar manualmente, bien para insertarles valores o bien para mostrarlos u ocultarlos. 

Lo primero que hago con ese subpanel, en la línea 91, es borrar su contenido para empezar con un lienzo en blanco.

En la línea 93 defino que quiero colar en columna descendente aquellos elementos que vaya añadiendo al subpanel.

Por último, añado los campos con las posiciones globales (líneas 96 y 101). En ambos casos hago lo mismo, creo un campo especializado en mostrar valores posicionales (Vector3Field). Luego, le doy valor a esos campos posicionales usando las propiedades de MeasuringTape que devolvían las respectivas posiciones globales (líneas 97 y 102). Como quiero que los campos sean de sólo lectura, y por tanto no se le puedan insertar valores manualmente, los deshabilito con SetEnabled(false) (líneas 98 y 103). Por último, añado los campos recién creados y configurados al subpanel (líneas 99 y 104).

Con esto ya tendríamos un regla para medir distancias completamente funcional... aunque bastante incómoda. Para usarla, tendríamos que crear un GameObject vacío dentro de la escena y luego añadirle el componente MeasuringTape. Ciertamente trabajoso. Podríamos simplificar las cosas creando un prefab que sólo incorporase el componente MeasuringTape. Así sólo habría que arrastrar el prefab a la jerarquía, cada vez que quisiéramos una regla en la escena. Sin embargo, es nos obligaría a tener que buscar el prefab en nuestras carpetas cada vez que necesitásemos medir algo. Por eso, lo que he hecho es crear una entrada en el menú principal del editor con la que crear una instancia del prefab cada vez que sea necesario. Veamos cómo lo he hecho.

Para añadir entradas al menú principal de Unity te basta con decorar un método estático con el atributo [MenuItem]. A este atributo se le pasa la ruta, dentro del menú principal, de nuestra entrada. Lo que ocurrirá a partir de entonces es que, cada vez que se pulse a esa entrada en el menú, se llamará al método estático.

En mi caso, he implementado el método estático en el fichero Assets/Editor/InstanceMeasuringTape.cs. Fíjate en que el atributo [MenuItem] está en el namespace de UnityEditor, así que un script que lo utilice tiene que situarse en la carpeta Editor.

Assets/Editor/InstanceMeasuringTape.cs
Assets/Editor/InstanceMeasuringTape.cs

Lo primero que hace el método, en la línea 15, es llamar a LoadAssetAtPath() para cargar el prefab con MeasuringTape del que hablábamos antes. La ruta donde buscar dependerá de cómo ejecutes la herramienta. Si copia-pegas todo el código directamente dentro de tu proyecto, tendrás que poner la ruta donde dejes el prefab (siendo Assets la raíz de la ruta). En mi caso, lo he configurado todo para que se ejecute como un paquete descargado desde GitHub con el Package Manager de Unity (en otro artículo explicaré cómo se hace). Así que la ruta tiene que ser la de la carpeta donde se instale el paquete. Los paquetes se instalan en la carpeta Packages, así que mi ruta parte de esa raíz, tal y como se puede ver en la línea 9.

Una vez cargado el prefab, en forma de GameObject, se puede instanciar dentro de la escena usando el método PrefabUtility.InstantiatePrefab() (línea 23). El resultado de esa llamada es que la instancia del prefab aparece en la escena, colgando de la raíz de la jerarquía.

Por último, como lo lógico es que quieras operar sobre la regla recién creada, en la línea 32 se selecciona dicha regla dentro de la jerarquía para que no tengas que buscarla para pulsar sobre ella. 

Y eso es todo. Espero que te haya resultado interesante y que te hay dado alguna idea para crear tus propias herramientas dentro de Únity. Como ya he mencionado en este artículo, en un futuro próximo espero poder sacar un rato para explicar cómo se puede hacer para colgar tus herramientas en GitHub de manera que se se puedan cargar, y mantener actualizadas, usando el PackageManager de Unity.

08 septiembre 2025

Herramientas para crear novelas visuales

En un artículo anterior repasamos algunas de las herramientas disponibles para crear el argumento de tu juego. En este vamos a ver algunas de las herramientas que puedes emplear para utilizar ese argumento para crea uno de los juegos más sencillos, y adictivos, que hay: las nivelas visuales.

Las novelas visuales son un género de videojuegos que se centran en la narrativa interactiva, donde el jugador toma decisiones que afectan la historia. Suelen tener un estilo visual de arte estático (como ilustraciones de personajes en 2D o 3D) y se presentan como una combinación de texto, imágenes y, a veces, música o voces. La jugabilidad se basa principalmente en leer diálogos y descripciones, tomar decisiones en momentos clave y, en algunos casos, resolver pequeños acertijos.

Se trata por tanto de un género técnicamente sencillo, pero que requiere de un argumento potente, complejo y que enganche al jugador a pesar de la simplicidad de la mecánica de juego. Por eso, estos juegos deben ofrecer una narrativa profunda, con historias complejas, que a menudo cuentan con múltiples finales a los que se llega dependiendo de las elecciones del jugador.

Conceptualmente, es un tipo de juego que debería resultarnos familiar a todos aquellos que nos criamos leyendo libros de "Elige tu propia aventura". Las novelas visuales son la trasposición a los videojuegos de aquella categoría de libros. Como videojuegos, empezaron a popularizarse en Japón, pero que ha ido popularizándose en el resto del mundo gracias a plataformas de juego como Steam o itch.io.

Puedes encontrar ejemplos de juegos de este tipo en: Phoenix Wright: Ace Attorney, The House in Fata Morgana o Fate/stay night.

Se trata por tanto de un género de juegos muy interesante si tienes la capacidad de crear un argumento cautivador, y puedes arroparlo con unas buenas ilustraciones y un sonido acorde, pero careces de los medios que requieren otros tipos de juegos (como programadores, animadores, modeladores o especialistas de efectos visuales).

En este artículo vamos a ver algunas de las herramientas que puedes utilizar para crear una novela visual contando sólo con esos tres ingredientes, argumento, ilustraciones y sonido, y minimizando (o eliminando del todo) la necesidad de otras habilidades, como la de programación.

Ren'Py

Ren'Py es un motor de desarrollo gratuito y de código abierto diseñado específicamente para crear novelas visuales y juegos narrativos interactivos. Es una de las herramientas más populares para este género, especialmente entre desarrolladores independientes, debido a su facilidad de uso, flexibilidad y comunidad activa.

Logo de Ren'Py
Logo de Ren'Py

Una vez instalado, funciona creando ficheros de texto con extensión .rpy. Estos ficheros utilizan una combinación de un lenguaje de scripting propio (similar a Python) y Python estándar. El scripting de Ren'Py es intuitivo, con comandos simples para diálogos, elecciones y transiciones, mientras que Python permite mayor personalización para funciones avanzadas. El resultado son ficheros de texto altamente autodescriptivos que la mayoría de las veces se leen casi como si fueran lenguaje natural.

Para trabajar con esos ficheros de texto, puedes usar un editor cualquiera o el que viene integrado con el entorno de Ren'Py, que además ofrece vista previa en tiempo real, lo que acelera el desarrollo. Se trata por tato de una herramienta con la que se pueden desarrollar novelas visuales muy vistosas sin necesidad de conocimientos técnicos profundos.

Para enriquecer las narraciones, soporta imágenes (PNG, JPG), animaciones, transiciones, música y efectos de sonido. También permite mostrar sprites de personajes con expresiones variables. También incluye un sistema automático para guardar partidas y puntos de control.

La integración del lenguaje Python dentro del engine permite a los desarrolladores pueden crear menús personalizados, sistemas de puntos, minijuegos o mecánicas únicas usando Python.

A la hora de llegar al máximo número de jugadores, Ren'Py te permite crear múltiples traducciones de tus juegos y exportarlos a diferentes plataformas, como Windows, macOS, Linux, Android, iOS y navegadores web.

La página de Ren'Py cuenta con una detallada documentación oficial, pero además hay multitud de foros, plantillas, tutoriales y assets compartidos por la comunidad para mejorar y facilitar el desarrollo de juegos con este engine.

Gracias a todas esas ventajas, Ren'Py se ha convertido en el engine con el que se han desarrollado éxitos como Doki Doki Literature Club, Katawa Shoujo o Long Live the Queen.

De todas las opciones que veremos en este artículo, es la que te recomiendo por defecto. Es difícil que te equivoques con ella. Y desde luego, siendo gratuita, el experimento no te costará nada. Sólo si este engine se quedase corto, por la razón que fuese, optaría por algunas de las otras opciones que paso a contarte.

Tyrano Builder

TyranoBuilder es un software de desarrollo de novelas visuales basado en una interfaz de arrastrar y soltar, ideal para los que prefieren evitar programar o que buscan una interfaz intuitiva. Permite crear juegos interactivos con diálogos, imágenes, música y elecciones, sin necesidad de escribir código, aunque ofrece opciones avanzadas para quienes quieran personalizar más.

Logo de Tyranno Builder
Logo de Tyranno Builder

Por tanto, su flujo habitual de trabajo supone usar su editor visual para construir tu novela visual añadiendo "componentes" (como diálogos, imágenes, sonidos) desde un menú. Si quisieras añadir funciones avanzadas, mecánizas de juego personalizadas o efectos complejos, podrías recurrir a TyranoScript, un lenguaje de scripting fuertemente basado en JavaScript. Su principal ventaja respecto a Ren'Py es esta componente visual que te permite hacer historias sencillas sin escribir nada que se parezca a código. Sin embargo, una vez que traspases cierto umbral, y quieras hacer cosas más sofisticadas, tendrás que usar TyrannoScript el cual me parece peor opción que el Python que ofrece Ren'Py.

Es compatible con múltiples formatos de imágenes y de audio, así como de vídeo (para cinemáticas o transiciones). Para mejorar visualmente el juego, la herramienta permite incluir efectos básicos como fundidos, movimientos de personajes, zooms o transiciones. También permite "bocadillos" para acercar más la estética de los diálogos a los comics.

Como en cualquier novela visual, la mecánica de juego que se puede implementar con esta herramienta se basa en mostrar diálogos con el texto y los nombres de los personajes. Estos diálogos son ajustables en velocidad y estilo. La herramienta permite crear elecciones que ramifican la historia según las elecciones que vaya haciendo el jugador. Estas ramificaciones pueden ser enriquecidas mediante variables simples (sin código) para rastrear elecciones o desbloquear contenido.

El editor de la herramienta permite probar el juego conforme va tomando forma. Lo que lo hace extremadamente rápido para llegar a un prototipo funcional y, de ahí, a una versión definitiva.

El juego resultante puede ser exportado a Windows, Mac, HTML5 y a dispositivos móviles, tanto iOS, como Android.

Tyranno Builder no es gratuito, aunque su coste es muy reducido (unos 15 €) y además se reduce a una compra única. Cuenta con plugins para extender su funcionalidad, aunque una gran mayoría de ellos parecen venir de Japón, donde esta herramienta parece ser especialmente popular.

Cuenta con una comunidad, pero es mucho más pequeña que la de Ren'Py, por eso es más difícil encontrar tutoriales para ella, especialmente en español. La página oficial tyranobuilder.com y las discusiones en Steam ofrecen soporte, pero no son tan extensas. Los tutoriales en YouTube (en inglés) son útiles, pero menos abundantes.

A diferencia de Ren'Py, Tyranno Builder no tiene juegos de gran éxito en su haber. Es más común en proyectos indie menos conocidos, publicados en plataformas como Itch.io. 

En general, Tyrano Builder lo usan creadores que quieren resultados rápidos sin programar. Lo cual no tiene nada de malo, de ser tu caso. Sólo ten en cuenta que a poco que quieras hacer más sofisticado tu juego, probablemente te traiga más cuenta optar por Ren'Py.

Visual Novel Maker

Visual Novel Maker (VNM) es un software comercial desarrollado por Degica (los creadores de RPG Maker) diseñado específicamente para crear novelas visuales. 

Logo de Visual Novel Maker
Logo de Visual Novel Maker

Al igual que Tyrano Builder, Combina una interfaz visual de arrastrar y soltar con opciones de scripting (JavaScript), lo que lo hace accesible para principiantes, pero también permite personalización para usuarios más avanzados. En este sentido se parece mucho a Tyrano Builder, pero tiene varias capacidades distintivas.

Para empezar, integra soporte para animaciones Live2D, que permite personajes con movimientos fluidos y expresiones dinámicas (como parpadeos, movimientos de cabeza o gestos) sin necesidad de configuraciones externas. Esto es ideal para proyectos con un enfoque más profesional o visualmente dinámico.

También ofrece una función de vista previa en tiempo real que permite probar cambios rápidamente, incluso en proyectos grandes. Esto agiliza el proceso de diseño y corrección, reduciendo la frustración durante la creación. Tyrano Builder también cuenta con una vista previa, pero son frecuentes las quejas sobre su lentitud y otros problemas (como retrasos o bugs al previsualizar escenas complejas).

El editor visual es más sofisticado que el de Tyrano Builder y te permite implementar mecánicas más complejas (como sistemas de variables, condiciones o transiciones avanzadas) sin necesidad de programar. Por ejemplo, puedes configurar sistemas de puntos o elecciones condicionales directamente en la interfaz. Es cierto que Tyrano Builder permite implementar las mismas funcionalidades, pero para hacerlo hay que tirar de TyranoScript.

Otra ventaja es que Visual Novel Maker cuenta con varios assets preinstlados (imágener, musica, etc) que pueden se útiles para montar tu prototipos.

Además, el consenso general es que la interfaz de usuario de Visual Novel Maker es pulida y moderna, con un diseño inspirado en RPG Maker. Si encima eres usuario de RPG Maker, te sentirás en casa. Otra relación con RPG Maker, es que ofrece compatibilidad con cierto plugings y recursos de esa herramienta, lo que puede ser útil si planeas incorporar elementos de RPG o usar assets diseñados para esta plataforma.

Los efectos visuales que puede ofrecer desde el editor visual son mucho más avanzados que los de Tyrano Builder, el cual, para conseguir resultados parecidos, tiene que tirar de scripting.

Exporta a Windows, Mac, Linux, Android, iOS y navegadores (HTML5). La exportación a móviles requiere configuración adicional (como Android SDK o Cordova), lo que puede ser complicado para principiantes.

En cuanto a la comunidad, es pequeña, aunque quizás algo mayor que la de Tyrano Builder gracias al tirón de RPG Maker.

La conclusión es que con Visual Novel Maker te resultará más fácil obtener un aspecto profesional para tu novela visual, comparado con Tyrano Builder. Claro que todo tiene un precio, y el de Visual Novel Maker es mayor (unos 60 €) que el de Tyrano Builder (unos 15 €), aunque sigue siendo una compra única. 

Al final, si el presupuesto no es un problema, y tienes buenos artistas que le saquen partido a la funcionalidad de Live2D, la opción más segura es la de Visual Novel Maker. 

¿Merece la pena frente a Ren'Py? Bueno, Ren'Py es gratuito. No cuenta con assets precargados, pero su comunidad es tan enorme que es muy fácil encontrar assets y plugins de todo tipo. Es cierto que Ren'Py se basa en ficheros de texto, pero eso puede ser una ventaja si piensas trabajar en grupo usando un repositorio de código. Por otro lado, soy un hater convencido de JavaScript (lo siento, es que es un lenguaje que no puedo ni ver, y mira que le he dado oportunidades) mientras que la opción de Ren'Py de ofrecer Python me parece ideal. Es cierto que Ren'Py no ofrece de serie animaciones Live2D, pero su comunidad acude al rescate y, gracias a ella, hay un complemento que lo permite, y encima con un mayor contro sobre los efectos y las transiciones gracias al Python. Quizás, la mayor ventaja de Visual Novel Maker es su vista previa permite probar cambios rápidamente sin exportar el juego, mientras que Ren'Py tiene que ejecutar el juego completo, aunque se puede saltar a secciones específicas usando etiquetas, lo que es más incómodo.

29 agosto 2025

Herramientas para desarrollar el argumento de un videojuego

La importancia del argumento depende del tipo de juego y su público objetivo. Hay juegos como Tetris o Among Us, en los que la narrativa es mínima, y la diversión radica en las mecánicas. Este tipo de juegos no necesitan un argumento complejo. 

Sin embargo, el argumento es un pilar fundamental para la experiencia en juegos de tipo narrativo, RPG o de aventuras. En estos juegos, el argumento es importante por múltiples razones. Un buen argumento crea un mundo creíble y personajes con los que los jugadores pueden empatizar, aumentando la inmersión. Historias bien desarrolladas generan emociones, motivando a los jugadores a continuar para descubrir qué pasa. El argumento proporciona un marco narrativo que da sentido a las acciones del jugador. Sin una historia, las mecánicas pueden sentirse vacías o repetitivas. Por ejemplo, en juegos como The Last of Us, el argumento impulsa las decisiones y hace que las mecánicas tengan peso emocional. Una narrativa sólida ofrece objetivos claros y razones para avanzar, ya sea salvar un mundo, vengar a un personaje o desentrañar un misterio. Esto mantiene el interés, especialmente en juegos largos. En un mercado saturado, un argumento original o bien ejecutado puede destacar un videojuego frente a otros con mecánicas similares. Títulos como Hollow Knight o Disco Elysium son ejemplos donde la narrativa eleva la experiencia. Un argumento con ramificaciones, elecciones morales o finales múltiples (como en Mass Effect o The Witcher 3) fomenta la rejugabilidad, ya que los jugadores quieren explorar diferentes desenlaces.

Por tanto, el proceso de desarrollo del argumento del juego es tan importante como el de la programación o el modelado de assets. En este artículo vamos a ver algunas herramientas especializadas que nos pueden ser útiles para crear el argumento de nuestro juego, así como para diseñar sus conversaciones.

Obsidian

Obsidian es una aplicación de toma de notas y gestión del conocimiento diseñada para crear y organizar contenido a través de notas interconectadas, utilizando un sistema basado en Markdown y un enfoque de "grafo de conocimiento" que visualiza las relaciones entre ideas. Aunque no está específicamente diseñada para el desarrollo de videojuegos, su flexibilidad, personalización y capacidad para manejar grandes cantidades de información la convierten en una herramienta valiosa para escritores, diseñadores narrativos y desarrolladores que trabajan en la planificación de historias, lore, guiones y documentación de proyectos de videojuegos.

Logo de Obsidian
Logo de Obsidian

Obsidian destaca como una solución ligera y versátil para la preproducción y organización, especialmente para proyectos indie o equipos pequeños. 

Con Obsidian cada nota puede enlazarse a otras mediante vínculos bidireccionales (similar a un wiki personal). Su vista de grafo muestra conexiones visuales entre notas, facilitando la exploración de ideas complejas. Por tanto, se trata de una herramienta ideal para mapear relaciones entre personajes, eventos y quests.

A la hora de editar, tienes dos modos principales: un editor de texto plano en el que empleas formato Markdown, y un modo Canvas que te ofrece un lienzo visual para conectar notas con flechas, similar a un tablero de ideas. Al crear una nueva nota, los enlaces a otras notas se crean usando enlaces de Markdown. Cuando creas un Canvas puedes crear dos tipos de nodos: cards, que vienen a ser nodos pequeños con apenas un título, y notas que ya tienen un texto completo de Markdown (puedes incluso importar una nota que haya creado aparte). Al final, el Canvas es un espacio visual para organizar notas como nodos conectados, ideal para mapear historias ramificadas o flujos narrativos.

Editando notas en Obsidian
Editando notas en Obsidian



El modo Canvas de Obsidian
El modo Canvas de Obsidian

Un posible flujo de trabajo podría ser hacer una lluvia de ideas y recoger las ideas sueltas en notas, para luego estructurarlas en un Canvas. 

Luego, al margen del Canvas, si necesitases una vista de alto nivel de todas tus notas, puedes abrir la vista de grafo que que muestra el árbol de una nota y sus enlaces con otras notas.

Otra característica muy potente es que permite etiquetar los elementos lo que facilita búsquedas avanzadas usando operadores booleanos.

Por defecto, Obsidian lo guarda todo en local, en archivos locales de texto plano que aseguran la portabilidad y el bajo consumo de recursos. Esos datos se pueden exportar a Markdown, HTML, PDF o Word. Sincroniza con Dropbox, iCloud.

Obsidian es gratuito, pero si quisieses sincronización entre todos tus dispositivos tendrías que pagar una pequeña subscripción. Si quisieses publicar notas en el sitio web de Obsidian Publish habría que pagar otra subscripción.

Todo lo anterior ya lo hacen una opción muy interesante para lo que buscamos en este artículo, pero es que, además, Obsidian cuenta con una comunidad hiperactiva en foros, discord y Reddit, donde ofrecen plantillas, ejemplos de flujos de trabajo específicos (por ejemplo para narrativa de videojuegos). Dicha actividad ha creado ya más de 2.600 plugins comunitarios, como por ejemplo:

  • Dataview: Crea tablas dinámicas para gestionar personajes, quests o ítems (e.g., "muestra todos los NPCs con estado 'aliado'").
  • Obsidian Tasks: Seguimiento de tareas para planificación de desarrollo.
  • Kanban: Tableros para gestionar sprints o milestones.
  • Excalidraw: Dibujos para storyboards o mapas.

Al final, no hay dos instalaciones de Obsidian iguales. Casa usuario se lo personaliza con múltiples plugins para personalizarse la herramienta a sus gustos particulares, lo que la hace una herramienta tremendamente potente.

Ink

Inkle Studios es un estudio independiente de desarrollo de videojuegos. Se especializan en juegos narrativos interactivos, es decir, títulos centrados en historias ramificadas, decisiones del jugador y narrativas no lineales, donde el texto y las elecciones del usuario son elementos clave para avanzar en la trama. 

El fruto de su labor no se limita a los videojuegos, sino que también han creado herramientas para su desarrollo. Entre ellas se encuentra Ink, un lenguaje de scripting narrativo open-source (bajo licencia MIT), diseñado específicamente para escribir historias altamente ramificadas en juegos. Ink no es un lenguaje de programación tradicional, sino un markup simple y elegante que permite a escritores y desarrolladores crear diálogos, elecciones y tramas complejas de manera eficiente. Ink se integra fácilmente con motores como Unity (a través de un plugin gratuito), Unreal Engine y Godot, y ha sido adoptado por estudios grandes e independientes.

Logo de Ink
Logo de Ink

Para que nos entendamos, Ink sería lo que utilizarían los autores de la popular serie de libros "Elige tu propia aventura" si quisieran escribir sus historias hoy. Con él puedes ofrecer elecciones al lector y dejar que la historia se vaya ramificando conforme se sucedan dichas elecciones.

Ink ofrece una sintaxis fácil de aprender para no programadores, pero potente para estructuras avanzadas (como bucles, listas y lógica condicional). Además, es muy ligero, por lo que el flujo de trabajo con él es muy rápido permitiendo ver los cambios prácticamente conforme se escriben.

Sintaxis de Ink
Sintaxis de Ink

Todas esas ventajas han propiciado que haya sido ampliamente usado en multitud de juegos (como Haven, NeoCab, Sable, Sea of Thieves y The Banner Saga 3, por ejemplo) y que haya abundantes recursos en Internet para aprender a usarlo.

Para facilitar más su uso, Inkle ofrece también un editor gratuito llamado Inky, disponible en la misma página que Ink. Es un editor minimalista, que ofrece una ventana de preview en la que puedes probar las opciones y ramificaciones que vayas escribiendo. También te alerta de los errores de sintaxis de Ink que cometas al escribir. Tiene versiones tanto para Windows, como para Linux y Mac.Y finalmente, lo más importante, te permite exportar a JSON para que puedas cargar toda la información de la historia desde el juego que estés desarrollando. 



Twine

Twine es una herramienta gratuita y de código abierto diseñada para crear ficción interactiva y juegos narrativos basados en texto, especialmente historias no lineales donde las elecciones del jugador determinan el rumbo de la narrativa. Creada en 2009 por Chris Klimas, es ampliamente utilizada tanto por desarrolladores principiantes como por profesionales en el desarrollo de videojuegos, escritura creativa, educación y proyectos artísticos. Lo que ofrece es similar a Ink, en el sentido de que permite crear historias interactivas en formato hipertextual, donde el jugador navega a través de nodos de texto (llamados "pasajes") conectados por enlaces. Cada pasaje contiene texto, opciones y, opcionalmente, código para manejar lógica, variables o multimedia. 

El problema que tiene es que no hay un camino claro y fácil para importar la historia desde un game engine (como sí había con Ink), por lo que el uso de Twine está más indicado para limitarse a darle forma al guion del juego o para crear un prototipo hiper sencillo para mostrar las posibles ramificaciones de dicho guion.

Logo de Twine
Logo de Twine

Twine es conocida por su simplicidad, accesibilidad y flexibilidad. Su editor visual permite arrastrar y conectar nodos, creando un mapa de la narrativa. También tiene un modo de código para personalizar la lógica del juego.

Los historias interactivas creadas en Twine se publican como archivos HTML, jugables en navegadores web, lo que los hace altamente portátiles. También se pueden exportar a otras plataformas con herramientas adicionales. Los archivos de salida se pueden volcar en varios formatos soportados, para permitir el posterior tratamiento y personalización de la historia. 

El uso de un editor visual permite que la edición de texto en sí sea mucho más sencilla que en le caso de Ink. Al final, la redacción se limita a escribir texto y añadir enlaces simples (por ejemplo, [[Ir a la cueva]]) para conectar pasajes. Aunque también se puede recurrir a JavaScript y macros para hacer cosas más avanzadas. 

El editor de Twine
El editor de Twine

Con todo ello se pueden crear historias altamente ramificadas, desde aventuras de "elige tu propia aventura" hasta narrativas complejas con variables (por ejemplo, puntos de salud, inventarios) y lógica condicional. 

La herramienta y su código están disponibles bajo licencia abierta GPL-3. Se puede usar en línea (twinery.org) o descargar para Windows, macOS y Linux. Cuenta, además, con una comunidad activa, tutoriales (como los de twinery.org), foros, y plantillas en plataformas como itch.io. También hay extensiones y complementos creados por la comunidad.

Yarn Spinner

Yarn Spinner es una herramienta desarrollada originalmente por el estudio australiano Secret Lab (creadores de Night in the Woods), aunque posteriormente parte del equipo se escindió del estudio de videojuegos, para centrarse en el desarrollo de la herramienta, pasando a llamarse como esta.

A medio camino entre el lenguaje de scripting de Ink, y la herramienta visual de Twine, utiliza un lenguaje de scripting simple llamado Yarn, inspirado en formatos como guiones de cine o teatro, que permite escribir diálogos en texto plano con elementos de control de flujo, variables y comandos. Luego, un plugin integrado con el engine se encarga de actuar como un intérprete que ejecuta estos scripts en tiempo de juego, enviando líneas de diálogo, opciones y comandos al engine. 

Portada de la página web de Yarn Spinner
Portada de la página web de Yarn Spinner

Algunos juegos realizados con Yarn Spinner son Night in the Woods, A Short Hike, DREDGE, Lost in Random, Frog Detective, Button City o Escape Academy.

Para la edición de los scripts, tienen una extensión para Visual Studio Code que ofrece un editor de texto con resaltado, para crear los scripts en Yarn, así como una ventana de grafo con la que ver las ramificaciones de la historia. 

Extensión de Yarn Spinner para Visual Studio Code
Extensión de Yarn Spinner para Visual Studio Code

También cuentan con una página web, en la que editar y probar scripts sencillos.

Las principales ventajas de Yarn Spinner son:

  • Flexibilidad Narrativa: Soporta historias altamente ramificadas, con memoria de elecciones previas (por defecto), storylets (contenido dinámico basado en saliencia) y grupos de nodos/líneas para organización.
  • Personalización: Integra multimedia (imágenes, audio, video) vía comandos. Incluye UIs prehechas (e.g., burbujas de diálogo, ruedas de opciones) y samples para customización.
  • Localización: Soporte robusto para traducciones, extrayendo strings a archivos separados (e.g., JSON o CSV) para herramientas como Unity Localization o I2 Localization, facilitando workflows multilingües.
  • Depuración y Herramientas: Errores con números de línea, vista previa en navegador, y soporte para voice-over (sincronización con líneas). Comunidad activa en Discord y GitHub.

Si usas Unity, estás de enhorabuena, porque es el único engine con el que tienen un plugin de integración oficial. El código del plugin para Unity está disponible en GitHub, con licencia MIT, por lo que puedes descargártelo e instalarlo en Unity de manera gratuita. Otra opción es recurrir al Unity Asset Store para comprar plugin para Unity, su importe no es muy elevado y sirve para financiar el desarrollo de la herramienta. También ofrecen otros complementos para Unity, como uno que permite mostrar el texto de las conversaciones en bocadillos tipo comic, y otro que permite tomar las decisiones usando una rueda de selección.

También hay plugin para Unreal, y otro para Godot, pero aún se encuentran en fase Beta y no los recomiendan para producción.

Articy Draft

Articy:draft (ahora conocido principalmente como articy:draft X en su versión más reciente) es una herramienta profesional de diseño narrativo y organización de contenido interactivo, desarrollada por Articy Software GmbH, una empresa alemana fundada en 2009.

Se trata de un software visual que actúa como una base de datos centralizada para crear, gestionar y planificar historias ramificadas, diálogos, misiones, personajes y otros elementos narrativos en proyectos interactivos, con un enfoque especial en el desarrollo de videojuegos. A diferencia de herramientas de scripting puro como Ink o Yarn Spinner, Articy:draft es más un entorno visual integral (similar a un "CMS narrativo" o sistema de gestión de contenido para juegos), que combina edición de flujos de historia, bases de datos de objetos y colaboración en equipo. 

Logo de Articy Draft
Logo de Articy Draft

Es ampliamente utilizado en la industria por estudios indie y AAA para manejar narrativas complejas, y ha sido clave en títulos como Disco Elysium, Suzerain, HipWitch, Saint Kotar, Garden Scapes y Spell Force III

Cuenta con un editor visual no lineal para el diseño de contenido interactivo, que unifica editores especializados (para diálogos, misiones, objetos, ubicaciones) en una sola interfaz. Permite representar gráficamente entidades de juego (como NPCs, ítems o quests) con automatizaciones, variables y lógica condicional, actuando como un "frontend visual" para datos de juego. No genera código ejecutable directamente, sino que exporta datos estructurados para integrarlos en motores de juego.

El editor visual de Articy Draft
El editor visual de Articy Draft

Utiliza vistas anidadas (Flow View) para mapear historias de alto nivel (capítulos) a detalles finos (líneas de diálogo). Incluye un editor de plantillas flexible para objetos de juego, un simulador para probar lógica (con soporte para voz y localización), y herramientas como un editor de ubicaciones vectorial para planificar mapas 2D.

Anidación de vistas en ArticyDraft
Anidación de vistas en ArticyDraft

Ofrece un modo de simulación que reproduce la historia con voz, idiomas y lógica, ideal para iterar antes de exportar. El modo de simulación permite comprobar la evolución de las variables que hayamos ligado a los diálogos y a las distintas elecciones, así como comprobar el efecto que tienen estas variables en la ruta a través de las historias.

Modo simulación de Articy Draft
Modo simulación de Articy Draft

Otras herramientas adicionales con las que cuenta son un panel de storyboarding; un editor de ubicaciones (útil para planificar niveles o quests); soporte para voz en off (generación TTS para prototipos y sincronización); localización integrada (exporta strings para traducción y reimporta); y extensiones de IA para generar diálogos, imágenes o traducciones automáticas (e.g., con DeepL).

Storyboarding en ArticyDraft

Editor de ubicaciones
Editor de ubicaciones

También sirve de base de datos en la que guardar la configuración de todos los NPC y objetos del juego. La idea es que los diseñadores del juego puedan manipular los datos desde la interfaz de Articy Draft, para luego exportar todos los datos de una vez y cargarlos desde el game engine.

Base de datos de personajes y objetos del juego
Base de datos de personajes y objetos del juego

En cuanto a integraciones con game engines, Articy Draft cuenta con assets oficiales para integrarse tanto con Unity como con Unreal. Para otros engines, Articy Draft también permite exportar a XML y a JSON. Si no fuera suficiente con lo anterior, también ofrecen un paquete de NuGet para hacerte tu propio paquete de integración.

Articy Draft sigue un modelo de licenciamiento por subscripción, pero tiene una modalidad gratuita, con todas las funcionalidades, y que incluso puede usarse para proyectos comerciales, con la única limitación de un máximo de 700 objetos a gestionar por proyecto. Aun así, esa cantidad de objeto es muy generosa, y probablemente más que suficiente para la mayor parte de los proyectos medianos y pequeños. En todo caso, es más que suficiente para probar la herramienta y decidir si merece la pena. Si necesitásemos más de 700 objetos en nuestro juego, podríamos acudir a cualquiera de las licencias de pago (las individuales son bastante asumibles).

Dialogic

La herramienta anterior sólo tenía integración directa con Unity y Unreal, así que, para equilibrar la cosa, ahora vamos a hablar de una que sólo existe para Godot: Dialogic.

Dialogic es un plugin para Godot orientado a hacer sistemas de diálogo interactivos, novelas visuales (visual novels), RPGs y gestión de personajes.  Desarrollado inicialmente por Emilio Coppola en 2021 como una solución para agregar conversaciones ramificadas de manera sencilla, ha evolucionado hasta convertirse en una herramienta madura y popular en la comunidad de Godot, especialmente para desarrolladores indie que buscan integrar narrativas complejas sin escribir código extenso desde cero. Está disponible bajo licencia MIT, lo que permite modificaciones y uso comercial libre. 

Logo de Dialogic
Logo de Dialogic

Proporciona un editor integrado en Godot para diseñar "timelines" (líneas de tiempo de diálogo), que son secuencias de eventos como texto, opciones del jugador, animaciones, condiciones lógicas y señales. Estos timelines se ejecutan en tiempo de juego para mostrar conversaciones dinámicas y con ramificaciones, eventos y elecciones. Se pueden añadir condiciones (if/else con variables), señales (para triggers en el juego), animaciones y fondos a dichas conversaciones.

Editor del Timeline de Dialogic
Editor del Timeline de Dialogic

Incluye un sistema de gestión de personajes con retratos, expresiones y colores personalizados, y soporta extensiones para eventos customizados.

Editor de personajes de Dialogic
Editor de personajes de Dialogic

Visualmente es completamente personalizable, con temas editables (colores, fuentes, estilos de burbujas de texto), soporte para audio (voz en off, SFX), animaciones (e.g., shake de pantalla) y eventos customizados con poco código GDScript. Incluye estilos prehechos como "text bubble" para novelas visuales.

También contempla la localización, permitiendo traducciones integradas con glosarios traducibles.

Cuenta con una comunidad muy activa que lo ha dotado de extensiones para que pueda interactuar con otros plugins como SmartShape2D para terrenos o Godot Steamworks para logros.

Si vas a desarrollar con Godot, Dialogic es la opción más sencilla y económica dado que está repleta de funcionalidades, ya está más que probada en multitud de juegos de Godot y es gratuita.

Scrivener

Todas las herramientas anteriores, salvo quizás Twine, contemplan cierto nivel de integración o compatilidad con game engines. Scrivener es una algo muy diferente. Se trata de una herramienta 100% pensada en escritores y guionistas.

Desarrollada por la compañía Literature & Latte, aunque no esté específicamente creado para el desarrollo de videojuegos, es una herramienta versátil que puede ser extremadamente útil para escribir y estructurar guiones de videojuegos, especialmente para proyectos narrativos como RPGs, aventuras gráficas, novelas visuales o cualquier juego con historias ramificadas

Logo de Scrivener
Logo de Scrivener

Toma la forma de un procesador de texto avanzado y herramienta de gestión de proyectos que combina escritura con organización de notas, investigación y estructuración no lineal. Permite dividir un proyecto en secciones manejables (capítulos, escenas, etc.), gestionar materiales de referencia (imágenes, PDFs, notas) y exportar en múltiples formatos. Además cada uno de los contenidos que se creen con Scrivener pueden ser enriquecidos con metadatos, notas, etiqueta y referencias.

Para planificar arcos narrativos ofrece un modo de visualización similar a un corcho en el que cada una de las secciones se visualiza como una tarjeta.

El corcho de Scrivener
El corcho de Scrivener

Todo el interfaz es muy flexible, jugando con él, y haciendo un uso adecuado de las etiquetas, se pueden configurar líneas de tiempo con la que desarrollar líneas argumentales paralelas.

 

Líneas de tiempo con Scrivener
Líneas de tiempo con Scrivener

No esperes herramientas para darle formato. En ese sentido, Scrivener es muy sencillo, casi primitivo. En realidad, está pensado para concentrarse en generar el contenido y luego exportarlo para darle formato en otras herramientas. Por ejemplo, mucha gente configura Scrivener para exportar el contenido generado a LaTeX y luego, desde un editor de LaTex, exportan a PDF con todo el formato de la plantilla de LaTeX empleada.

Por tanto, Scrivener es una excelente herramienta para escribir y organizar el guion de un videojuego en la fase de preproducción, especialmente para estructurar narrativas complejas y mantener el lore organizado. Sin embargo, no está diseñado para simular interactividad ni integrarse directamente con motores de juego, por lo que necesitarás combinarlo con herramientas como Twine (para prototipos rápidos), Dialogic (para Godot), Yarn Spinner (para Unity) o Articy:draft (para proyectos AAA). Si tu enfoque es escribir un guion detallado antes de la implementación técnica, Scrivener es una gran elección; si necesitas interactividad inmediata, opta por una herramienta específica para videojuegos.