martes, 24 de junio de 2025

Quiero empezar por el final

 


   Agradeciendo a todos aquellas personas o entidades, que de una forma u otra contribuyen y en muchos casos de manera altruista, a orientar y formar. Estamos en una sociedad circular, en la que lo que pasa allí, se acaba sintiendo aquí. Que quiero decir con esto, pues que gracias a que es así, algunos como es mi caso, crecemos y creemos.

   Esta formación tiene su origen en Extremadura, mas concretamente en Almendralejo, localidad cercana a Badajoz, que a través de IRIA (Incubadora de Realidades Inmersivas de Almendralejo), ofrece un programa de apoyo a las iniciativas de emprendedores, autónomos y Pymes con proyectos de innovación y desarrollo en el ámbito de la industria 4.0, Realidad Virtual, Aumentada, Realidad Mixta y Extendida y es aquí donde se propone un curso de formación, gratuito, Introducción a Unreal Engine 5.

   Se ha impartido, durante 30 intensas horas y no son todas las que se echan, porque hablamos de un motor, no solo de videojuegos, con inmensas posibilidades, de la mano experta de Javier Jurado Gámez (Unreal Gold Instructor partner for Epic Games y Director en Cursos Unreal Engine) y esto no es cualquier cosa. 30 horas puede parecer poco, pero con Javier esto adquiere otra dimensión y si, aunque no se lo crean, es básico.

   El programa ha sido extenso e intenso, muy ambicioso y ha desbordado las 30 horas por todos lados. Realizado entre el 08 de mayo y el 12 de junio del 2025 y a buen seguro, este no será el último. Abarca desde Interfaz de Usuario, Navegación y fundamentos 3D en Unreal, Creación de Niveles y Escenarios, Materiales y Texturas, Iluminación, Programación con Blueprints, Interfaz de Usuario (UI), Sonidos y Partículas y finalmente, Animación y Cinemática.

   Bienvenida sean estas iniciativas, otros lo tomen como ejemplo y que se multipliquen en el futuro.

Respecto del curso, vamos con esas "cosillas" que pueden ser de interés y que aparecen en tu día a día.

1.- Rutas importantes (No os perdáis).

Ruta por defecto de la carpeta VAULTCACHE,  donde se instalan los assets desde FAB.

C:/ProgramData/Epic/EpicGamesLauncher/VaultCache/

Ruta por defecto donde se instala el Launcher.

C:\Program Files (x86)\Epic Games

Ruta por defecto donde se instalan las vesiones del motor.

C:\Program Files\Epic Games

 

 2.- Atajos, algunos de los vistos, son interesantes.


Generalidades

ctrl + B -> Asset Actions -> Migrate (en proyecto, buscar carpeta Content), en mi anterior formación este me lo perdí y me hubiera venido de perlas.

alt + F4 -> Matar la aplicación.

ctrl + L -> Control dirección del sol (si, pero la tecla ctrl de la derecha del teclado).

Materiales

C -> en el grafo, cajita de comentarios.

L + botón izq. ratón -> Muestra la luz incidiendo en la muestra de material.

Blueprints

alt + botón izq. ratón -> Elimina línea.

ctrl + botón izq. ratón -> Mueve punto a otro nodo.

Nº atajo + botón izq. ratón -> Pone el nodo correspondiente (a la derecha podemos desplegar y ver los atajos).

Seleccionamos una línea de nodos, pulsamos Q y se alinean los cables (para los ordenados, se recomienda).

ctrl + C y ctrl + V -> Por medio de un archivo .txt y así lo pasamos entre proyectos, los BluePrint, (y esto porqué no me lo enseñasteis antes?, increíble!!!).

IA

P -> Vemos la zona en la que puede desplazarse el enemigo (esto parece evidente, pero a mi me costó encontrarlo).

Viewport

F8 -> Puedo seleccionar en el editor, en play mode cualquier actor del mundo y poder localizarlo en el Outliner (muy interesante).


3.- De todas las carpetas que crea Unreal, unas son importantes y otras, no tanto.

Carpetas Importantes: Config, Content y *.uproject

Carpetas que se pueden eliminar (estas las vuelve a crear, es importante en algunos cuelgues, realizar esta operación): Intermediate, Saved, DerivedDataCache.


4.- El Gizmo, esas flechas de colores.

      En Unreal Engine, el eje X positivo se representa con el color rojo y es el que se considera la dirección Forward por defecto. Por si te interesa el esquema completo del gizmo:

X (rojo): adelante (Forward)

Y (verde): a la derecha (Right)

Z (azul): hacia arriba (Up)


   Este sistema de coordenadas es típico en motores de juegos como Unreal, a diferencia de otros como Unity, donde Forward suele estar en el eje Z.

        Cambiar el punto de pivote de un mesh, podemos hacerlo desde el Modeling Mode -> XForm -> Edit Pivot -> Elegimos la posición nueva que nos interese.


5.- Cuando queremos incluir un video y que se renderice en el juego, pues...

   los videos deben ponerse en la carpeta .../Content/Movies, sino no compila el video (esto lo cuenta Javier, pero otros se lo callan).


6.- Respecto de los materiales.

   Esto no es solo en Unreal, también en Unity y supongo que en la mayoría de los motores. Los materiales se crean basados en unos shaders, estos se escriben en un lenguaje propio llamado HLSL (High-Level Shader Language). En la Programación de shaders: se usa para escribir vertex shaders, pixel shaders y más.


7.- Colocar un objeto en tu personaje.

Abrimos el Skeletal Mesh del personaje. Tienes que ver el Skeleton Tree.

Buscamos el hueso donde queremos poner nuestro objeto (mochila, arma,...), por ejemplo la mano derecha y si no existe el socket (según versiones), lo creamos con botón derecho ratón, Add Socket, sobre el hueso en cuestión.

Sobre el Socket creado, click botón derecho y Add Preview Asset, buscamos y seleccionamos. Resituamos el objeto con las herramientas de transformación y listo.

Ahora, vamos a tu personaje, seleccionamos el Viewport, añadimos un componente de Static Mesh para el objeto y lo arrastramos bajo nuestro Mesh.

En Details de nuestro objeto, seleccionamos el Static Mesh del objeto y buscamos nuestro Parents Socket, anteriormente creado.

Si es necesario, reinicia los valores del Transform, si tu objeto no queda bien situado.

Ahora nuestro personaje porta el objeto, donde le hemos dicho.


8.- Muchas son las cosas que se pueden hacer desde la línea de comando, como botón de muestra.

   En línea consola de comandos, en Unreal, poner HighResShot 2 y toma una imagen de pantalla. Interesante para documentar tu trabajo.


9.- Cuando empaqueto el proyecto para Windows, y quiero personalizar el icono del ejecutable. Después de varios intentos, en diferentes resoluciones, encuentro la solución, la Community es grande. Os lo pongo mas abajo, junto con la aplicación web que he usado para crear el favicon.ico, pero lo mas importante, no os lo vais a creer y es como debeis proceder, borrar la caché de temporales y reiniciar el PC, o no se actualizaran los cambios.


10.- Mixamo.

Descargar de Mixamo un personaje, formato FBX Binary(.fbx) y Pose T-pose y guardamos el personaje.fbx.

Descargamos una animación, formato FBX Binary(.fbx), Skin, Without Skin, Frames por segundo, 30 fps y KeyFrame Reduction, none. En las animaciones Walk, marcar In Place.

Vamos al Content de tu proyecto, creamos una carpeta llamada Characters y 4 subcarpetas: Mesh, Materials, Textures, Animations.

Damos a Import desde la carpeta Mesh y lo primero que añado es el character. Muevo texturas, Materiales y animaciones.

Después, vamos a importar la animación y en la ventana de dialogo decimos a que skeleton pertenece y listo.

Como podemos hacer el retargeting, es decir reorientar los huesos. 

Click derecho en la animación, Retarget Animations, queremos pasar la animación a Manny, autoretargeting y exportamos la animación adaptada, con prefijo MM_, para que coincida con las del personaje receptor, en este caso Manny.


11.- Links de interés.


Recursos

Mixamo, para descargar personajes y animaciones.

Audacity , para editar sonidos, util para pasar a mono y reducir tamaño del audio.

Sonidos libre , para uso particular.

Convierte una imagen en un favicon.ico (es el formato de archivo usado por Unreal para cambiar el icono del ejecutable).


Materiales


How To Create And Use LODs In Unreal Engine 4/5 To Make Your Games Run Smoother.

How To Create Atlas Master Materials in Unreal Engine 5.


Iluminación


Creating Natural Lighting in Unreal Engine: A Step-by-Step Guide.


Landscape


Creating Non-Repeating Landscape Materials in Unreal Engine | Texture Blending & Macro Variations.


Sonidos


Cómo añadir SONIDOS de PISADAS en Tercera Persona en Unreal Engine 5.


Niagara


Cómo crear NIAGARA en forma de static o skeletal MESH en Unreal Engine 5.


IA en Unreal Engine


Inteligencia Artificial en Unreal Engine 5 🤖/ Enemigo que te persigue 🏃🏼 y sigue puntos aleatorios !


UI


Make An Easy WIN and LOSE System For Your Games In Unreal Engine 5 Using Blueprints.

Unreal Engine 5 Health and Damage System Tutorial [2023].


Cinematics


How to Create an Opening Cinematic in Unreal Engine 5

Unreal Engine 5 Beginner Tutorial Part 16 : Cameras, Rig Rail, and Crane

Full Beginner Filmmaking Masterclass for Unreal Engine 5 - Make your First Cinematic.

Cómo Hacer CINEMÁTICAS en UNREAL ENGINE 5 | Principiante (Sequencer UE5).


Sockets


Cómo Añadir y Cambiar Armas en tu Personaje de Unreal Engine 5 (Paso a paso)


Empaquetado


Ojo, si quieres cambiar el icono en el ejecutable, tienes que tener en cuenta esto que se dice aquí.


Documentación, un tema que ha quedado pendiente y fundamental para el control de versiones, sobre todo si trabajas en equipo.


Fundamentos de Git


Sobre la plataforma Android, no llegamos a ver nada, pero me los apunto para verlo en un futuro proximo

Android


Unreal Engine 5.5: Android Target Platform Setup & Build .APK | Step-by-Step Guide


AR Android


AR from scratch in 10 minutes using Unreal Engine 5.3!


_

Especial mención.


Los promotores y medios

Incubadora de Realidades Inmersivas de Almendralejo

Plataforma de Capacitación Tecnológica de Extremadura


El Profesor

Javier Jurado Gámez


Los Alumnos

Que viven este camino, con admirable pasión y sacrificio.


sábado, 1 de febrero de 2025

Entre entusiastas y detractores




El uso de la llamada Inteligencia Artificial se está generalizando en el mundo de las marcas y aplicaciones. El tiempo de las versiones Beta a dado paso, masivamente, a las versiones oficiales y no existe hoy en día, una marca que se precie, que no haya incorporado esta tecnología a su buque insignia.

Yo como aficionado a las tecnologías no paro de sorprenderme de la rapidez en su avance y la curiosidad me llama.

Entre entusiastas y detractores no es un artículo que pretende ahondar en la brecha abierta por el uso de estas tecnologías, sino más bien en su buen uso, para el desarrollo de nuevas ideas, provocando el cambio en los modelos de aprendizaje, derribando fronteras y procurando un cambio progresivo y beneficioso al conjunto de la sociedad.

Uno de los grandes miedos hacia esta, podría ser, la dependencia que se crea con su uso generalizado y para ello, nada mejor que el debate abierto y permanente. Una mente lucida, nunca deja en manos de otro, lo que considera importante, al menos sin una correcta supervisión. Y esta, ¿la dejaremos también en manos de la que podiamos llamar "IA vigilante"?.

Para el ejemplo que os traigo he usado Replit, un IDE en la nube que incorpora dos poderosas herramientas basadas en Inteligencia Artificial, Agent y Assistant. No se trata de contar las bonanzas de la aplicación, que sin duda las tiene. Tampoco tengo claro, si lo que hay detrás es unicamente la IA, o un equipo mixto (Humano/Máquina > 1 o Humano/Máquina < 1), así que me gustaría pensar que el merito se debe a su gran equipo humano de desarrollo.

La idea, que no es original pero para mí novedosa y bastante técnica, trata de crear un "input remote" o mando a distancia para un videojuego desarrollado con Unity, utilizando para ello un dispositivo móvil. Como siempre, esto es solo un prototipo de desarrollo, sin animo de lucro, con el foco puesto en el aprendizaje. Todas las herramientas usadas, son solo para uso particular y poder dar una salida a mi inquietud y curiosidad. A continuación os muestro un enlace de YouTube, donde se puede ver en que consiste facilmente Vídeo InputRemote

Las explicaciones y el código que he usado en este desarrollo lo podeis consultar libremente en https://github.com/jmcaneda/MobileJoystickControllerDef

Para llevarla a cabo, he tomado uno de "mis pequejuegos", el que mejor podría adaptarse, desarrollado en Unity.

Vamos a comenzar por a describir el apartado del videojuego con el motor Unity y el código que tiene mas relación con esta idea.

Unity

En la Build Settings

  • Utilizo como plataforma WebGL, que como sabéis significa Web Graphics Library, es una API (interfaz de programación de aplicaciones) utilizada para renderizar gráficos 3D y 2D en navegadores web sin necesidad de plugins y permite a los desarrolladores crear gráficos interactivos y animaciones utilizando JavaScript y el estándar de gráficos OpenGL ES. La mayoria de los navegadores web ya incorporan este framework por defecto.

En Player Settings. Estos parámetros han sido consultados en el manual de Unity https://docs.unity3d.com/2022.3/Documentation/Manual/webgl-deploying.html

  • Compression Format: a Gzip.
  • Data Caching: a check.
  • Decompression  Fallback: a check.

¿Qué nos proporciona la Build?. Las carpetas Build, TemplateData y el archivo index.html. Si comprimimos el conjunto en un archivo .zip y lo subimos a la Plataforma de videojuegos Indie itchio, indicándole que se pueden ejecutar en un navegador web, ya podriamos disfrutar del mismo, utilizando como mando del videojuego, el propio teclado.

Pero..., ¿dónde colocamos todo este código para que podamos ejecutar nuestra aplicación correctamente?. Pues colocamos el resultado de la Build en Unity en la carpeta static del servidor, tal cual, sin modificar nada. ¿Quiere decir esto que si en vez del juego utilizado MaribelProject, lo cambio por otra Build, respetando su ubicación, funcionaría el resto?. La respuesta es si. Podemos reutilizar todo el código y solo, crear nuestro juego y podremos manejar los inputs, desde cualquier dispositivo móvil. Esto es lo fantástico!!!.

Archivos de la Build en Unity


static/Build/
 ├── Builds.data
 ├── Builds.framework.js
 ├── Builds.loader.js
 └── Builds.wasm
 			
static/TemplateData/
├── style.css
└── [assets visuales]
          
index.html

Del código C#, el que mayor interés tiene para la cuestión que estamos tratando es PlayerController.cs, de este extraeremos la parte que nos interesa resaltar. Son la declaración de clases de los diferentes tipos de datos que manejaremos en los diferentes eventos.

void HandleJoystickInput(string jsonData)
En este evento se recibirán los datos x e y del Joystick para el desplazamiento del personaje.
void HandleButtonInput(string jsonData)
En este evento se recibirán los datos state y action, acerca de las teclas pulsadas para el desplazamiento del personaje y visión de cámara.
void HandleInputMethod(string jsonData)
En este evento se recibirá el dato state, sobre el método de input elegido, a off, desde teclado, a on, desde dispositivo móvil.

      
      
      void HandleJoystickInput(string jsonData)
      {
          if (GameManager.instancia.inputRemote)
          {
              JoystickData data = JsonUtility.FromJson(jsonData);
              movement = new Vector3(data.x, 0, data.y) * moveSpeed;

              animator.SetFloat("Horizontal", data.x);
              animator.SetFloat("Vertical", data.y);
          }
      }

      void HandleButtonInput(string jsonData)
      {
          if (GameManager.instancia.inputRemote)
          {
              ButtonData data = JsonUtility.FromJson(jsonData);
              if (data.state == "pressed")
              {
                  switch (data.action)
                  {
                      case "up":
                          {
                              movement = Vector3.forward * moveSpeed;
                              animator.SetFloat("Horizontal", movement.x);
                              animator.SetFloat("Vertical", movement.y);
                              break;
                          }
                      case "down":
                          {
                              movement = Vector3.back * moveSpeed;
                              animator.SetFloat("Horizontal", movement.x);
                              animator.SetFloat("Vertical", movement.y);
                              break;
                          }
                      case "left":
                          {
                              movement = Vector3.left * moveSpeed;
                              animator.SetFloat("Horizontal", movement.x);
                              animator.SetFloat("Vertical", movement.y);
                              break;
                          }
                      case "right":
                          {
                              movement = Vector3.right * moveSpeed;
                              animator.SetFloat("Horizontal", movement.x);
                              animator.SetFloat("Vertical", movement.y);
                              break;
                          }
                      case "A":
                          {
                              break;
                          }
                      case "B":
                          {
                              // Iniciar el desplazamiento a la siguiente esquina
                              GameManager.instancia.indiceEsquinaActual = (GameManager.instancia.indiceEsquinaActual + 1) % GameManager.instancia.esquinas.Length;
                              GameManager.instancia.offset = GameManager.instancia.esquinas[GameManager.instancia.indiceEsquinaActual];
                              break;
                          }
                  }

              }
              else if (data.state == "released")
              {
                  if (data.action != "A" && data.action != "B")
                  {
                      movement = Vector3.zero;
                  }
              }
          }
      }
      
      void HandleInputMethod(string jsonData)
      {
          InputMethodData data = JsonUtility.FromJson(jsonData);
          switch (data.state)
          {
              case "on": GameManager.instancia.inputRemote = true; break;
              case "off": GameManager.instancia.inputRemote = false; break;
          }
      }
      
      [System.Serializable]
      public class JoystickData
      {
          public float x;
          public float y;
      }

      [System.Serializable]
      public class ButtonData
      {
          public string action;
          public string state;
      }

      [System.Serializable]
      public class InputMethodData
      {
          public string state;
      }
    
    

Objeto importante en Unity

En Unity, debe existir el objeto MaribelController y tener como componente, entre otros el script PlayerController.cs

Python y JavaScript

Esta es la parte en la que la asistencia de la IA de Replit, no con pocos intentos en la fase de depuración, facilitó las claves para encaminar este desarrollo, a buen término.

Este proyecto implementa una comunicación bidireccional en tiempo real,       entre un controlador móvil y un juego Unity WebGL, utilizando WebSocket como protocolo de comunicación.


Componentes Principales


Servidor WebSocket (app.py)


Implementado con Flask-SocketIO
Gestiona conexiones y desconexiones
Retransmite eventos entre el controlador y Unity

Cliente Controlador (controller.js)


Implementa la interfaz de usuario del controlador
Captura eventos táctiles y de botones
Emite eventos WebSocket al servidor

Cliente Unity (websocket.js)


Recibe eventos del servidor
Comunica con el juego Unity via SendMessage
Gestiona la conexión WebSocket del lado del juego


Vamos a verlo sobre un diagrama de bloques.



[Dispositivo Móvil] --> (WebSocket) --> [Servidor Flask] --> (WebSocket) --> [Unity WebGL]
     ^                                                                            |
     |                                    Feedback                                |
     +--------------------------------------------------------------------------- +
 			


Partes del código que cabe resaltar



game.html, este es el verdadero contenedor de Unity. Tomamos todo lo que nos interesa del código index.html, de la build de Unity y lo reescribimos en este.


websocket.js, recibe los eventos del servidor y los comunica a Unity vía SendMessage


handleGameControl(data) {
        if (!this.gameInstance) {
            console.warn('Game instance not ready, retrying connection...');
            setTimeout(() => this.socket.connect(), 1000);
            return;
        }

        // Send the control data to Unity
        switch(data.type) {
            case 'joystick':
                this.gameInstance.SendMessage('MaribelController', 'HandleJoystickInput', 
                    JSON.stringify(data.data));
                break;
            case 'button':
                this.gameInstance.SendMessage('MaribelController', 'HandleButtonInput',
                    JSON.stringify(data.data));
                break;
            case 'inputMethod':
                this.gameInstance.SendMessage('MaribelController', 'HandleInputMethod',
                    JSON.stringify(data.data));
                break;
        }
}
        

Importante, se puede observar que SendMessage busca un objeto llamado MaribelController y los métodos HandleJoystickInputHandleButtonInputHandleInputMethod, incluidos en el componente PlayerController.cs


Error en la versión de producción (Deployments)

Cuando ya disponía de todo el código probado en desarrollo, al pasarlo a producción en Replit (Deployments), se producía un error, que pese a estar documentado en parte en los manuales de Unity, no lo estaba para su uso con servidores Flask. Paso a describirlo, junto con la solución adoptada.

"WebAssembly streaming compilation failed! This can happen for example if "Content-Encoding" HTTP header is incorrectly enabled on the server for file /static/Build/Builds.wasm, but the file is not pre-compressed on disk (or vice versa)".

En app.py podrás ver como se ha resuelto este tema y la clave, en el siguiente código.

    @app.route('/static/Build/')
    def serve_build(filename):
        try:
            response = send_from_directory('static/Build', filename)
            if filename.endswith('.wasm'):
                response.headers['Content-Type'] = 'application/wasm'
                response.headers['Cross-Origin-Embedder-Policy'] = 'require-corp'
                response.headers['Cross-Origin-Opener-Policy'] = 'same-origin'
                response.headers['Cross-Origin-Resource-Policy'] = 'cross-origin'
                response.headers['Cache-Control'] = 'no-cache'
                response.headers['Accept-Ranges'] = 'bytes'
                # Asegurarse de que no haya compresión
                response.direct_passthrough = True
                if 'Content-Encoding' in response.headers:
                    del response.headers['Content-Encoding']
                if 'Content-Length' in response.headers:
                    del response.headers['Content-Length']
            return response
        except Exception as e:
            app.logger.error(f'Error serving {filename}: {str(e)}')
            return str(e), 500
      

Técnica empleada y herramientas adicionales🔧

Asset Store 🏬

He utilizado los siguientes packages de Asset Store, casi siempre en su versión free o con mínima inversión.



Links de interés 🔗

He utilizado los sonidos de nuestro querido "Chiquito de la calzada".

El juego original, sin input remote, en WebGL y teclado, podéis probarlo sin problemas. Este es un videojuego regalo y me sirve como base para el desarrollo de este artículo. Gracias Maribel.

Elementos necesarios 🔑

  • La app requiere un dispositivo móvil, con capacidad para el escaneo de código QR y navegador web, compatible o habilitado para JavaScript (la mayoría ya lo tienen configurado por defecto).
  • La aplicación comenzará con el linkado desde el navegador web, compatible con WebGL (la mayoría ya lo son por defecto). Recomiendo que se realice desde equipo de sobremesa o portátil.
  • Desde el dispositivo móvil escanearemos el código QR y dispondremos el mismo en apaisado. Es importante que veamos el "connected" en verde, esto es indicativo que podemos hacer uso del dispositivo.
  • El foco debe estar puesto en el navegador, esto lo podemos conseguir posicionando el ratón en el mismo. Cambiaremos el input mode, en el dispositivo móvil, de Off a On y ya está, podremos manejar a nuestro personaje "Maribel", en su recorrido por las calles, escuchando los mensajes y procurando no ser convertida por los "UrbanZombies", de dos maneras: como Joystick o por medio de los botones de desplazamiento. El botón "B", esta programado para el cambio de posición de la cámara.
  • Requiere de una conexión a internet.

_

C.A.C. (Soho Málaga), supuso para nosotros (los de entonces), un lugar de encuentro.


domingo, 23 de junio de 2024

M-ART Soho

Soy un entusiasta de las TIC en general, su aplicación en Realidad Aumentada y las posibilidades que nos brinda como medio de interacción, con realidades ficticias.

Con esta breve experiencia pretendo explicar con sensaciones y por medio de un dispositivo móvil (Android), la mezcla entre interactuar en una escena virtual, con otra de realidad aumentada y como puedo pasar de una a otra sin perder la identidad en la ficción.


Para ello me sirvo de varias herramientas de desarrollo, principalmente:

Unity 2022.3 (como motor de videojuegos), Microsoft Visual Studio Community 2022 (64 bits) 17.10.3, los packages AR Foundation 5.1 , Google ARCore 5.1 , Lightship AR 3.5, Maps 0.4 y WPS 3.5 de Niantic, para la aplicación de realidad aumentada.


Ante todo aclarar que es un prototipo en desarrollo, agradecer a entidades y particulares, la documentación existente, ejemplos y foros que tanto me han ayudado en el aprendizaje y desarrollo de esta experiencia.


También advertir que este tipo de aplicaciones deben probarse en entornos seguros, ya que por sus características, el yo protagonista como es lógico, puede perder parte del control sobre el espacio real que le rodea.


La idea original es presentar espacios y personajes de interés público, de forma que el arte y la cultura esten siempre presentes y para ello imagino un viaje entre mundos a través de portales, ubicados en diferentes puntos de interés y representados por rocas estelares en el mapa.


Esta primera parte presenta a modo de ejemplo algunas ubicaciones, que nos servirán de entrada al portal, en la actualidad siempre con el mismo escenario, una especie de nave. Ya que puede resultar difícil de probar, al ser necesario estar en el lugar físico en concreto, podemos pasar directamente del mapa al portal y viceversa, mediante botón.


Atravesar las rocas supone pasar de tu realidad a una, en un espacio de ficción y bajo una temática futurista.


Salvo los botones para el paso entre escenas, al mapa o al portal, el manejo lo realizamos en su totalidad a través del móvil. Se situará una marca en el suelo, en un caso servirá para ayudar a fijar el portal en la ubicación deseada (un tap proyectará la puerta, doble tap fijará la puerta en la ubicación deseada) y en otros casos para pasear a la mascota, simplemente arrastra la marca y la mascota la seguirá (previamente debes haberla liberado de su habitáculo).


Para una mejor experiencia, se recomienda que se realice en un espacio amplio y seguro, de forma que podamos movernos por el espacio ficticio sin dificultad. Por otro lado también es recomendable atravesemos el portal totalmente y nos situemos siempre de un lado o al otro del mismo, con el fin de experimentar los cambios completamente.


Espero que con estas indicaciones sea suficiente para disfrutar de esta experiencia, aún en desarrollo, pero que tanto me está sorprendiendo.

Técnica empleada y herramientas adicionales🔧

Asset Store 🏬

He utilizado los siguientes packages de Asset Store, siempre en su versión free.


  • Robot Sphere.
  • 3D Stylized Animated Dogs kit.
  • Stylized Astronaut.
  • Hi-Rez Spaceships Creator Free Sample.
  • Sci-Fi Texture pack 1.
  • Planets of the Solar System 3D.

Elementos necesarios 🔑

  • La app ha sido probada en un dispositivo Redmi Note 8 Pro con versión Android 10, que dispongo para mis desarrollos, aunque es compatible desde la versión 8. Los dispositivos deben ser compatibles con ARCore (consultar para una mayor información https://developers.google.com/ar/devices), para una mejor experiencia AR.
  • La instalación es sencilla, descargar el apk e instalarlo en el móvil con Android. Lógicamente se preguntará por la confianza en el origen de la aplicación y si se da permiso, se instalará.
  • Requiere de una conexión a internet, a través de la red móvil o Wifi. Al arrancar la aplicación se solicitarán los permisos sobre uso de localización y cámara, necesarios para su utilización, para una experiencia completa. El estado Running, que aparece en la primera escena de presentación, indica que los servicios están operativos para su correcto uso, es posible que se requiera un nuevo reinicio en la app. Una vez se hayan concedido los permisos, estos pueden revocarse, o bien en ajustes desde el móvil buscando la aplicación o desinstalando la app.

_

✨Soho Málaga, ubicaciones actuales de las rocas estelares.


viernes, 1 de diciembre de 2023

Vídeo en Unity utilizando Gaussian splats

 🎥


La creación de un vídeo en Unity utilizando Gaussian splats comprende varias etapas tanto técnicas como creativas. Comenzamos con la captura del entorno mediante vídeo y posterior procesado. Estos datos se exportan como Gaussian splats en formato .ply, un formato compatible con herramientas de modelado 3D y motores de juegos como Unity.

Una vez en Unity, el siguiente paso es la importación del personaje y sus animaciones. Luego, se prepara la cinemática, empleando técnicas de programación en C# específicas de Unity. Este paso es crucial para dar vida al personaje y ambientar la narrativa del vídeo.



Finalmente, las escenas son grabadas en tiempo real dentro de Unity y exportadas en formatos de vídeo compatibles. La etapa final consiste en la integración y edición de los diferentes segmentos de vídeo, utilizando un software de edición de vídeo. Aquí, se realiza la sincronización precisa de audio y vídeo para completar el proyecto.

_

Fuentes consultadas y aplicaciones usadas:👇🏻


🛠️

  • Aplicación para la captura de escenarios para su posterior visualización 3D. En particular, lo he realizado a través de captura de video desde movil para su posterior procesado y descarga por la aplicación. https://lumalabs.ai/luma-api

  • Es una fuente muy consultada y mantiene actualizado su repositorio. Ha sido fundamental su package para la visualización en Unity. Contiene herramientas para la limpieza y depuración de la captura, pero en esta ocasión al ser algo experimental no he usado. Muy importante para la integración con Unity es que se use con DX12 or Vulkan on Windows, por lo que habras de configurarlo en Proyect Settings -> Player -> Other Settings -> Graphics APIs for Windows. https://github.com/aras-p/UnityGaussianSplatting

  • El "Character" usado esta descargado de esta base de personajes y animaciones de Adobe, exportado como .fbx para su posterior integración en Unity. https://www.mixamo.com/
  • Unity es una plataforma reconocida para la creación de videojuegos, entre otros. https://unity.com/es

_

✨La captura inicial fue tomada en el Soho Málaga, en una de sus pinturas en fachada, en concreto la que luce el CEIP García Lorca.


✨Mención especial para el grupo musical 🎶 Loquillo y los Trogloditas y su tema “Quiero un camión”, utilizado en la base rítmica.