{"id":68145,"date":"2025-05-31T08:47:20","date_gmt":"2025-05-31T13:47:20","guid":{"rendered":"https:\/\/niixer.com\/?p=68145"},"modified":"2025-05-31T09:40:19","modified_gmt":"2025-05-31T14:40:19","slug":"desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final","status":"publish","type":"post","link":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/","title":{"rendered":"Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final"},"content":{"rendered":"\n<p>Este documento describe el proceso de desarrollo del videojuego&nbsp;<em>SpeedAndJump<\/em>, un proyecto en Unity dise\u00f1ado en perspectiva de primera persona. El juego consiste en guiar a un personaje a trav\u00e9s de diversos retos, plataformas m\u00f3viles, enemigos y trampas, con el objetivo final de alcanzar un castillo. Durante el desarrollo se implementaron sistemas de vida, detecci\u00f3n de ca\u00eddas, animaciones controladas por condiciones, inteligencia artificial b\u00e1sica en enemigos (como abejas voladoras), y una interfaz de usuario que refleja el estado del jugador. Adem\u00e1s, se incluyeron men\u00fas interactivos con m\u00fasica y video, as\u00ed como escenas de Game Over y Victoria. El documento incluye tambi\u00e9n los scripts utilizados, explicados con su funcionalidad y prop\u00f3sito, brindando una visi\u00f3n completa del dise\u00f1o t\u00e9cnico y jugable del proyecto.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"463\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-697.png\" alt=\"\" class=\"wp-image-68140\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-697.png 900w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-697-300x154.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-697-768x395.png 768w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"898\" height=\"458\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-698.png\" alt=\"\" class=\"wp-image-68141\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-698.png 898w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-698-300x153.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-698-768x392.png 768w\" sizes=\"auto, (max-width: 898px) 100vw, 898px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfDWzWuwkyxR1h7VNsGX-poXeqSJ0mWh9YUCf5Y2cQYi_5Ek3PbqzfkNOuY9ZRVjzqFAJz-T6QxfFjnGyPNPjK6UQoyFHwaUaPSkHe5OEQtIqutmFfG8VK7u3monTlPdSQ1Q_SBbm6lcodks24Uz6E?key=6mDFG3dtcEk5M1o4tDZoBQ\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 1<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Importaci\u00f3n de Assets y Configuraci\u00f3n Inicial del Personaje<\/strong><\/h2>\n\n\n\n<p>Todos los modelos 3D y animaciones utilizados en el juego fueron importados desde el paquete&nbsp;<strong>Ultimate Platformer Pack<\/strong>&nbsp;de&nbsp;<strong>Quaternius<\/strong>, descargado desde el sitio oficial de Unity&nbsp;<a href=\"https:\/\/assetstore.unity.com\/\">Asset Store<\/a>. El paquete fue incorporado al proyecto arrastrando su carpeta directamente al panel&nbsp;<strong>Project<\/strong>&nbsp;de Unity, permitiendo as\u00ed su reconocimiento autom\u00e1tico por el motor. Desde esta ubicaci\u00f3n se seleccionaron los modelos, animaciones y objetos f\u00edsicos requeridos para el desarrollo del entorno y la mec\u00e1nica del juego.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXcYOn3dolLUPvBwY1UKGBRQe3Ui5cV_CxDI40mvIJFOXzTGzkuiULw1uqWcFToLrRyDoJBK4pAjy4fSkAGdFNUOKUfz6HF1JdITbRSYQGFr32A_BaovNtHCCdKAhf1l7Y5otT7519oQa4Rk4pmLGQ?key=6mDFG3dtcEk5M1o4tDZoBQ\" alt=\"figura 1\n\"\/><\/figure>\n\n\n\n<p>figura 2<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeCG8gDcAVMUKtIEYu8PXv-RN3v2FZNB_R4e7wssHMeVWoB03fG8L3TMPWY5zzhttqbl02BeABfjpEAGsmLQpjtjJWC0RzDj_CE5pT3KAlNry-RbjbLUU03UzyJ9UTKvgv7tzjoD5j3vhegODMaPuA?key=6mDFG3dtcEk5M1o4tDZoBQ\" alt=\"figura 2\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 3<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXcwLIJ_idlddewAAOpUxlXx0XeOLcO3jRakGjXUPtFTLts1Ry0FyR2_ffmW8IuD_vmGjAW5IfdbAvN7MKbOW1LhvOyA4Wv_KPlMQERZd4bzw72kBTkn-g037K4qVQTAjd5xAPEb6LsWrPIVcDtfBuY?key=6mDFG3dtcEk5M1o4tDZoBQ\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 4<\/p>\n\n\n\n<p>Se llevaron a cabo los siguientes pasos clave para la configuraci\u00f3n inicial del personaje principal y los elementos f\u00edsicos del entorno:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Importaci\u00f3n del Modelo del Jugador: El modelo 3D fue importado en formato\u00a0<code>.<\/code><em><code>FBX<\/code>\u00a0<\/em>desde el paquete\u00a0<em>Ultimate Platformer Pack<\/em>. En la pesta\u00f1a\u00a0<em>Rig<\/em>\u00a0del Inspector, se configur\u00f3 el tipo de animaci\u00f3n como Humanoid para facilitar la integraci\u00f3n con el sistema de animaci\u00f3n de Unity.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"518\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-684-1024x518.png\" alt=\"\" class=\"wp-image-68108\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-684-1024x518.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-684-300x152.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-684-768x389.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-684-1536x777.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-684.png 1915w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Sistema de Animaciones: Las animaciones correspondientes fueron arrastradas a un Animator Controller, donde se definieron los estados y transiciones. Se configuraron par\u00e1metros como\u00a0<code>isRunning<\/code>\u00a0(booleano) para controlar el movimiento, y\u00a0<code>Die<\/code>\u00a0(Trigger) para gestionar la animaci\u00f3n de muerte. Se desactiv\u00f3 la opci\u00f3n Has Exit Time en la transici\u00f3n hacia la animaci\u00f3n de muerte para permitir una respuesta inmediata ante eventos de colisi\u00f3n letal.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"518\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-685-1024x518.png\" alt=\"\" class=\"wp-image-68109\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-685-1024x518.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-685-300x152.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-685-768x388.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-685-1536x776.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-685.png 1915w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>F\u00edsica del Entorno: A los elementos del entorno (como plataformas, obst\u00e1culos y superficies) se les asignaron componentes Rigidbody (cuando se requer\u00eda din\u00e1mica) y Collider (BoxCollider, MeshCollider o CapsuleCollider, seg\u00fan el objeto), con el fin de gestionar las colisiones y simular interacciones f\u00edsicas realistas.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"523\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-686-1024x523.png\" alt=\"\" class=\"wp-image-68110\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-686-1024x523.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-686-300x153.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-686-768x393.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-686-1536x785.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-686.png 1915w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Control del Personaje: Se utiliz\u00f3 el componente CharacterController para el movimiento del jugador, acompa\u00f1ado de scripts personalizados que gestionan la l\u00f3gica de salto, detecci\u00f3n de ca\u00edda, y condiciones de muerte (por ejemplo, ca\u00edda desde cierta altura o colisi\u00f3n con elementos hostiles).<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"521\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-687-1024x521.png\" alt=\"\" class=\"wp-image-68111\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-687-1024x521.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-687-300x153.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-687-768x390.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-687-1536x781.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-687.png 1914w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 8<\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Sistema de Vida y Detecci\u00f3n de Ca\u00eddas<\/strong><\/h1>\n\n\n\n<p>Se implement\u00f3 un sistema de vidas que determina cu\u00e1ntas veces el jugador puede caer desde una altura peligrosa antes de activar el estado de Game Over. La l\u00f3gica se basa en dos condiciones principales:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"535\" height=\"180\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-689.png\" alt=\"\" class=\"wp-image-68113\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-689.png 535w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-689-300x101.png 300w\" sizes=\"auto, (max-width: 535px) 100vw, 535px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 9<\/p>\n\n\n\n<p><strong>Detecci\u00f3n de Ca\u00edda por Altura:<\/strong>&nbsp;Si el jugador cae desde una altura superior al valor definido como&nbsp;<code>minFallHeight<\/code>, se considera una ca\u00edda peligrosa y se decrementa el contador de vidas disponibles.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"535\" height=\"180\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-690.png\" alt=\"\" class=\"wp-image-68114\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-690.png 535w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-690-300x101.png 300w\" sizes=\"auto, (max-width: 535px) 100vw, 535px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 10<\/p>\n\n\n\n<p><strong>L\u00edmite de Posici\u00f3n Vertical:<\/strong>&nbsp;Independientemente de la altura desde la que se cay\u00f3, si la posici\u00f3n vertical del jugador (<code>transform.position.y<\/code>) desciende por debajo de un umbral cr\u00edtico definido (por ejemplo,&nbsp;<code>deathYThreshold<\/code>), se ejecuta autom\u00e1ticamente la p\u00e9rdida de una vida. Esta condici\u00f3n asegura que ca\u00eddas prolongadas fuera del escenario tambi\u00e9n sean detectadas como fallos<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXcLZwp5Xb-m63LAk-RLD93_ikK92ICCxEQ7r9DwifjdRk7yWvLW4zAonaGsN3eyzvlvVo8v3K50cmOTBk5gmwMVOn4tcSgQ9fJmXev65MV2V7P0zHugV4sv6fvzkeP7NDT-inzqoSAhiCkKEvDljQ?key=6mDFG3dtcEk5M1o4tDZoBQ\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 11<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sistemas de animaci\u00f3n<\/h2>\n\n\n\n<p>Las animaciones del personaje fueron gestionadas a trav\u00e9s de un Animator Controller, que defini\u00f3 el flujo de estados como:<\/p>\n\n\n\n<p><em><strong><code>Idle<\/code>&nbsp;<\/strong><\/em>\u2013 cuando el personaje est\u00e1 detenido.<\/p>\n\n\n\n<p><em><strong><code>Walk<\/code>&nbsp;\/&nbsp;<code>Run<\/code><\/strong><\/em>&nbsp;\u2013 durante el movimiento a baja o alta velocidad.<\/p>\n\n\n\n<p><strong><em><code>Die<\/code>&nbsp;\u2013<\/em><\/strong>&nbsp;animaci\u00f3n de muerte activada tras una ca\u00edda o evento letal.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXeewBa40uHsPNodRhJUPP1VMaNhCNXE4jdHL2Ug8GlhCl6gIkhoJ_MXdSzi1uViQl5gRyOWAlGhYAZ3q9CaFdF-6NSCPUm2iHFzgInvT5B63tGSyppD6veNtQOb5t8KznyQFRWAEmNW1THam5c-TWE?key=6mDFG3dtcEk5M1o4tDZoBQ\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 12<\/p>\n\n\n\n<p>Para activar la animaci\u00f3n de muerte, se defini\u00f3 un par\u00e1metro de tipo&nbsp;<strong>Trigger<\/strong>&nbsp;llamado&nbsp;<code>Die<\/code>, el cual es invocado desde el script del controlador de vida en el momento en que el jugador pierde una vida.<\/p>\n\n\n\n<p>Con el fin de asegurar que la animaci\u00f3n de muerte se reproduzca completamente antes de que el personaje reaparezca, se utiliz\u00f3 una&nbsp;<strong>corrutina<\/strong>&nbsp;(<code>Coroutine<\/code>) que introduce un retardo basado en la duraci\u00f3n exacta de la animaci\u00f3n. Solo despu\u00e9s de ese intervalo se restablece la posici\u00f3n del jugador al punto de inicio o&nbsp;<code>respawn<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"447\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-692-1024x447.png\" alt=\"\" class=\"wp-image-68116\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-692-1024x447.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-692-300x131.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-692-768x335.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-692-1536x670.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-692.png 1606w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 13<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Interfaz de Usuario (UI) y Control de Da\u00f1o<\/strong><\/h2>\n\n\n\n<p>El sistema de interfaz de usuario fue dise\u00f1ado para reflejar en tiempo real el estado de vidas del jugador. Para ello, se implement\u00f3 un script llamado&nbsp;<strong><code>UIManager<\/code><\/strong>, encargado de actualizar din\u00e1micamente los elementos visuales (como \u00edconos de vidas o contadores num\u00e9ricos) cada vez que se produce una p\u00e9rdida de vida.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"509\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-693-1024x509.png\" alt=\"\" class=\"wp-image-68117\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-693-1024x509.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-693-300x149.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-693-768x382.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-693-1536x763.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-693.png 1916w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 14<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Creaci\u00f3n e Integraci\u00f3n del Enemigo: Abeja<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Importaci\u00f3n del Modelo 3D<\/strong><\/h3>\n\n\n\n<p>El modelo de la abeja fue importado en formato&nbsp;<code>.FBX<\/code>&nbsp;y ubicado en la ruta:&nbsp;<code>Assets\/Enemies\/Bee<\/code>.<\/p>\n\n\n\n<p>En el panel&nbsp;<strong>Inspector<\/strong>, se configur\u00f3 el tipo de&nbsp;<strong>Rig<\/strong>&nbsp;como&nbsp;<code>Humanoid<\/code>&nbsp;o&nbsp;<code>Generic<\/code>, dependiendo del formato del asset original y la compatibilidad de las animaciones.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Configuraci\u00f3n del Prefab<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Se gener\u00f3 un\u00a0<strong>Prefab<\/strong>\u00a0denominado\u00a0<code>Bee<\/code>\u00a0arrastrando el modelo desde el proyecto a la carpeta\u00a0<code>Assets\/Prefabs<\/code>.<\/li>\n\n\n\n<li>Se a\u00f1adieron los siguientes componentes:\n<ul class=\"wp-block-list\">\n<li><strong>Animator<\/strong>: con el\u00a0<code>BeeAnimatorController<\/code>\u00a0asignado.<\/li>\n\n\n\n<li><strong>Rigidbody<\/strong>: configurado con:\n<ul class=\"wp-block-list\">\n<li><code>Mass = 1<\/code><\/li>\n\n\n\n<li><code>Drag = 0.5<\/code><\/li>\n\n\n\n<li><code>Use Gravity = false<\/code>\u00a0(para simular vuelo continuo).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>SphereCollider<\/strong>: utilizado para detectar colisiones f\u00edsicas. Se mantuvo\u00a0<code>Is Trigger = false<\/code>\u00a0para permitir interacci\u00f3n f\u00edsica con el jugador.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>El objeto fue etiquetado con:\n<ul class=\"wp-block-list\">\n<li><code>Tag = Enemy<\/code><\/li>\n\n\n\n<li><code>Layer = Enemies<\/code><br>Esto facilita la identificaci\u00f3n mediante scripts y la gesti\u00f3n de colisiones con capas espec\u00edficas.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"528\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-694-1024x528.png\" alt=\"\" class=\"wp-image-68118\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-694-1024x528.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-694-300x155.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-694-768x396.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-694-1536x792.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-694.png 1913w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 15<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Configuraci\u00f3n del Animator Controller<\/strong><\/h3>\n\n\n\n<p>Se configur\u00f3 el&nbsp;<code>BeeAnimatorController<\/code>&nbsp;con los siguientes par\u00e1metros y estados:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Par\u00e1metros:<\/strong>\n<ul class=\"wp-block-list\">\n<li><code>isFlying<\/code>\u00a0(bool): activado por defecto para mantener el estado de vuelo.<\/li>\n\n\n\n<li><code>Attack<\/code>\u00a0(Trigger): utilizado para iniciar la animaci\u00f3n de ataque cuando se detecta al jugador.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Estados:<\/strong>\n<ul class=\"wp-block-list\">\n<li><code>BeeFlying<\/code>: clip de animaci\u00f3n de vuelo, configurado como\u00a0<strong>Default State<\/strong>\u00a0(flecha naranja), con la opci\u00f3n\u00a0<strong>Loop Time<\/strong>\u00a0activada.<\/li>\n\n\n\n<li><code>Attack<\/code>: animaci\u00f3n de ataque activada mediante trigger.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Transiciones:<\/strong>\n<ul class=\"wp-block-list\">\n<li><code>Any State \u2192 Attack<\/code>: condici\u00f3n\u00a0<code>Attack<\/code>\u00a0(Trigger activado).<\/li>\n\n\n\n<li><code>Any State \u2192 BeeFlying<\/code>: condici\u00f3n\u00a0<code>isFlying == true<\/code>.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Se desactivaron\u00a0<strong>Has Exit Time<\/strong>\u00a0y\u00a0<strong>Write Defaults<\/strong>\u00a0en transiciones espec\u00edficas para asegurar una respuesta inmediata y optimizar el control sobre los par\u00e1metros del Animator.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXfxtYM3a9JLtPtlIdH0tMJ9XeC4kMyminLBMOEHio5CPzYnV9VUeXiy1NCks43KybRJgbssv45rc69bxVY7tvPUW36sZ7kVlCFxdUHvIZWhA7PapV4-OCuEWkD5fkR-1D1wtiE9VE96pSjnMEchjPs?key=6mDFG3dtcEk5M1o4tDZoBQ\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 16<\/p>\n\n\n\n<p><strong>Script&nbsp;<code>BeeMovement.cs<\/code>&nbsp;\u2014 Movimiento y Ataque del Enemigo Abeja<\/strong><\/p>\n\n\n\n<p>El script&nbsp;<code>BeeMovement.cs<\/code>&nbsp;controla el comportamiento de patrullaje, persecuci\u00f3n y ataque del enemigo tipo abeja. Sus principales componentes funcionales son:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Inicializaci\u00f3n (<code>Start()<\/code>)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>void Start() {<br>    animator = GetComponent&lt;Animator&gt;();<br>    animator.SetBool(\"isFlying\", true); \/\/ Estado inicial de vuelo<br>    player = GameObject.FindGameObjectWithTag(\"Player\").transform; \/\/ Referencia al jugador<br>}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Actualizaci\u00f3n de Comportamiento (<code>Update()<\/code>)<\/h3>\n\n\n\n<p>En cada frame, se eval\u00faa la distancia al jugador y se ejecutan distintas acciones:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void Update() {<br>    float distanceToPlayer = Vector3.Distance(transform.position, player.position);<br>    <br>    if (distanceToPlayer &lt;= followRange) {<br>        \/\/ Movimiento hacia el jugador<br>        transform.position = Vector3.MoveTowards(transform.position, player.position, speed * Time.deltaTime);<br>        animator.SetBool(\"isFlying\", true);<br>        <br>        \/\/ Ataque si est\u00e1 en rango y respetando el cooldown<br>        if (distanceToPlayer &lt;= attackRange &amp;&amp; Time.time - lastAttackTime &gt;= attackCooldown) {<br>            animator.SetTrigger(\"Attack\");<br>            lastAttackTime = Time.time;<br>        }<br>    } else {<br>        \/\/ Patrullaje flotante (Idle)<br>        FloatIdle();<br>    }<br>}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>followRange<\/code><\/strong>: distancia m\u00e1xima para comenzar a seguir al jugador.<\/li>\n\n\n\n<li><strong><code>attackRange<\/code><\/strong>: distancia m\u00ednima para activar el ataque.<\/li>\n\n\n\n<li><strong><code>lastAttackTime<\/code><\/strong>\u00a0y\u00a0<strong><code>attackCooldown<\/code><\/strong>: variables para controlar la frecuencia de ataque y evitar ataques continuos.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"630\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-695-1024x630.png\" alt=\"\" class=\"wp-image-68119\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-695-1024x630.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-695-300x184.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-695-768x472.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-695.png 1233w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 17<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">M\u00e9todo de Movimiento Flotante (Idle)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>void FloatIdle() {<br>    float yOffset = Mathf.Sin(Time.time * floatSpeed) * floatAmplitude;<br>    transform.position = new Vector3(transform.position.x, initialY + yOffset, transform.position.z);<br>}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Simula un movimiento vertical suave con\u00a0<strong>Mathf.Sin<\/strong>\u00a0para dar sensaci\u00f3n de vuelo o patrullaje sin jugador cerca.<\/li>\n\n\n\n<li>Se recomienda almacenar el valor\u00a0<code>initialY<\/code>\u00a0en\u00a0<code>Start()<\/code>\u00a0para conservar el nivel base del eje Y.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-rt.googleusercontent.com\/docsz\/AD_4nXcvTNUJVOxfgVx01GuH0wYDihd6MrlE5FGXPYdfma7vu1wVFk9SaJyx5Mc6LBhrtybYIbBIUuXfN1bjRq3BhIAct8dFqiAVpUtYSZiNdZjY2_keIInXAhDAASN-89BLi932Ibk7KeLVtLYMBlxYE30?key=6mDFG3dtcEk5M1o4tDZoBQ\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 18<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Evento de Ataque:&nbsp;<code>DealDamage()<\/code><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>public void DealDamage() {<br>    \/\/ Este m\u00e9todo se llama desde un evento en el clip de animaci\u00f3n 'Attack'<br>    if (Vector3.Distance(transform.position, player.position) &lt;= attackRange) {<br>        player.GetComponent&lt;PlayerHealth&gt;().TakeDamage(damageAmount);<br>    }<br>}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Este m\u00e9todo se conecta directamente desde el\u00a0<strong>evento de animaci\u00f3n<\/strong>\u00a0del clip de ataque.<\/li>\n\n\n\n<li>Asegura que el da\u00f1o se inflija solo si el jugador est\u00e1 dentro del rango al momento del impacto.<\/li>\n\n\n\n<li>Llama al m\u00e9todo\u00a0<code>TakeDamage()<\/code>\u00a0del componente\u00a0<code>PlayerHealth<\/code>\u00a0para reducir vidas<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"501\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-696-1024x501.png\" alt=\"\" class=\"wp-image-68120\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-696-1024x501.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-696-300x147.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-696-768x376.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-696-1536x752.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-696.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 19<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementaci\u00f3n de Men\u00fa Principal con Canvas<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Creaci\u00f3n de Escena&nbsp;<code>MainMenu<\/code><\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Se cre\u00f3 una nueva escena\u00a0<code>MainMenu.unity<\/code>.<\/li>\n\n\n\n<li>Se a\u00f1adi\u00f3 a\u00a0<strong>Build Settings<\/strong>\u00a0para garantizar su correcta carga como primera escena del juego.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"898\" height=\"469\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-679.png\" alt=\"\" class=\"wp-image-68074\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-679.png 898w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-679-300x157.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-679-768x401.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-679-390x205.png 390w\" sizes=\"auto, (max-width: 898px) 100vw, 898px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 20<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Configuraci\u00f3n del Canvas<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Se a\u00f1adi\u00f3 un\u00a0<code>Canvas<\/code>\u00a0al escenario.<\/li>\n\n\n\n<li><strong>Render Mode<\/strong>:\u00a0<code>Screen Space - Overlay<\/code>\u00a0para una interfaz n\u00edtida y adaptativa en cualquier resoluci\u00f3n.<\/li>\n\n\n\n<li>Se ajustaron dimensiones y anclajes para una experiencia responsiva.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"529\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-683-1024x529.png\" alt=\"\" class=\"wp-image-68080\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-683-1024x529.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-683-300x155.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-683-768x396.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-683-1536x793.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-683.png 1875w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 21<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Elementos de UI<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Bot\u00f3n \u201cPlay\u201d<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Tipo:\u00a0<code>Button (TextMeshPro)<\/code>.<\/li>\n\n\n\n<li>Evento\u00a0<code>OnClick()<\/code>\u00a0asignado a\u00a0<code>MainMenuController.PlayGame()<\/code>, encargado de cargar la siguiente escena de juego.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Texto descriptivo<\/strong>:\n<ul class=\"wp-block-list\">\n<li>A\u00f1adido al Canvas.<\/li>\n\n\n\n<li>Tipograf\u00eda elegante con\u00a0<code>TextMeshPro<\/code>, tama\u00f1o y color ajustados para legibilidad y est\u00e9tica.<\/li>\n\n\n\n<li>Centrado y estilizado para acompa\u00f1ar el dise\u00f1o general del men\u00fa.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"898\" height=\"524\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-680.png\" alt=\"\" class=\"wp-image-68077\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-680.png 898w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-680-300x175.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-680-768x448.png 768w\" sizes=\"auto, (max-width: 898px) 100vw, 898px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 22<\/p>\n\n\n\n<p><strong>Fondo de Video<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Se cre\u00f3 la carpeta\u00a0<code>Assets\/Videos<\/code>\u00a0e import\u00f3 un archivo\u00a0<code>.mp4<\/code>.<\/li>\n\n\n\n<li>Se a\u00f1adi\u00f3 un componente\u00a0<code>VideoPlayer<\/code>\u00a0al Canvas:\n<ul class=\"wp-block-list\">\n<li><strong>Render Mode<\/strong>:\u00a0<code>Camera Near Plane<\/code>\u00a0(se renderiza detr\u00e1s de los elementos UI).<\/li>\n\n\n\n<li><strong>Target Camera<\/strong>:\u00a0<code>MainCamera<\/code>.<\/li>\n\n\n\n<li><strong>Loop<\/strong>: activado.<\/li>\n\n\n\n<li><strong>Play On Awake<\/strong>: activado.<\/li>\n\n\n\n<li><strong>Audio Output Mode<\/strong>:\u00a0<code>None<\/code>\u00a0(audio silenciado para no interferir con la m\u00fasica de fondo).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Se ajust\u00f3 el orden de render para mantener los elementos UI por encima del video.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"524\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-682-1024x524.png\" alt=\"\" class=\"wp-image-68079\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-682-1024x524.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-682-300x154.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-682-768x393.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-682-1536x786.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-682.png 1918w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 23<\/p>\n\n\n\n<p><strong>M\u00fasica de Fondo<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Se import\u00f3\u00a0<code>MenuMusic.mp3<\/code>\u00a0en la carpeta\u00a0<code>Assets\/Audio<\/code>.<\/li>\n\n\n\n<li>Se cre\u00f3 un\u00a0<code>GameObject<\/code>\u00a0llamado\u00a0<code>MusicPlayer<\/code>\u00a0con componente\u00a0<code>AudioSource<\/code>:\n<ul class=\"wp-block-list\">\n<li><strong>AudioClip<\/strong>: asignado a\u00a0<code>MenuMusic.mp3<\/code>.<\/li>\n\n\n\n<li><strong>Play On Awake<\/strong>: activado.<\/li>\n\n\n\n<li><strong>Loop<\/strong>: activado.<\/li>\n\n\n\n<li><strong>Volumen<\/strong>: ajustado a\u00a0<code>0.3<\/code>\u00a0para no opacar efectos futuros del juego.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"524\" src=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-681-1024x524.png\" alt=\"\" class=\"wp-image-68078\" srcset=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-681-1024x524.png 1024w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-681-300x153.png 300w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-681-768x393.png 768w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-681-1536x786.png 1536w, https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/image-681.png 1916w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center\">figura 24<\/p>\n\n\n\n<p>Anexo Completo de Scripts con C\u00f3digo y Descripci\u00f3n<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">AnimationEventRelay.cs.<\/h2>\n\n\n\n<p>Sirve como conexi\u00f3n entre una acci\u00f3n animada y la forma en que el jugador ataca.Captura un Evento de Animaci\u00f3n y redirige la solicitud al m\u00e9todo de ataque del PlayerController. Coordina las animaciones con la implementaci\u00f3n del da\u00f1o, garantizando precisi\u00f3n en el tiempo. con tecla E<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br><br>public class AnimationEventRelay : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public PlayerController playerController;<br><br>&nbsp;&nbsp;&nbsp; \/\/ Este m\u00e9todo ser\u00e1 llamado por el evento de animaci\u00f3n<br>&nbsp;&nbsp;&nbsp; public void PerformAttack()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (playerController != null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; playerController.PerformAttack();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">BeeMovement.cs<\/h2>\n\n\n\n<p>Regula las acciones de la abeja rival: flotaci\u00f3n sin movimiento, seguimiento al jugador, animaci\u00f3n de ataque y asistencia de da\u00f1o.Administra los estados de inactividad en el aire y la persecuci\u00f3n\/ataque seg\u00fan las distancias.Presenta un enemigo que se mueve de forma din\u00e1mica y pone a prueba al jugador.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br><br>public class BeeMovement : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public float floatSpeed = 2f;<br>&nbsp;&nbsp;&nbsp; public float floatAmount = 0.2f;<br>&nbsp;&nbsp;&nbsp; public float followRange = 6f;<br>&nbsp;&nbsp;&nbsp; public float attackRange = 1.2f;<br>&nbsp;&nbsp;&nbsp; public float moveSpeed = 3f;<br>&nbsp;&nbsp;&nbsp; public float attackCooldown = 1.0f;<br><br>&nbsp;&nbsp;&nbsp; private Vector3 startPosition;<br>&nbsp;&nbsp;&nbsp; private Transform player;<br>&nbsp;&nbsp;&nbsp; private Animator animator;<br>&nbsp;&nbsp;&nbsp; private float lastAttackTime = -Mathf.Infinity;<br><br>&nbsp;&nbsp;&nbsp; void Start()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startPosition = transform.position;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; animator = GetComponent&lt;Animator&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GameObject playerObj = GameObject.FindGameObjectWithTag(\"Player\");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (playerObj != null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player = playerObj.transform;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; void Update()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (player == null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FloatIdle();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float distance = Vector3.Distance(transform.position, player.position);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (distance &lt;= followRange)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Seguir al jugador<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vector3 targetPos = player.position;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; targetPos.y = transform.position.y;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transform.position = Vector3.MoveTowards(transform.position, targetPos, moveSpeed * Time.deltaTime);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Atacar si est\u00e1 en rango<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (distance &lt;= attackRange)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (Time.time - lastAttackTime &gt;= attackCooldown)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (animator != null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; animator.SetTrigger(\"Attack\");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastAttackTime = Time.time;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FloatIdle();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; void FloatIdle()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float newY = startPosition.y + Mathf.Sin(Time.time * floatSpeed) * floatAmount;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transform.position = new Vector3(transform.position.x, newY, transform.position.z);<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; \/\/ Este m\u00e9todo debe ser llamado por un evento en la animaci\u00f3n de ataque<br>&nbsp;&nbsp;&nbsp; public void DealDamage()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (player == null) return;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float distance = Vector3.Distance(transform.position, player.position);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (distance &lt;= attackRange)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PlayerLifeSystem pls = player.GetComponent&lt;PlayerLifeSystem&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pls != null &amp;&amp; pls.CurrentLives &gt; 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pls.TakeDamage();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">CameraFollow.cs<\/h2>\n\n\n\n<p>Establece una c\u00e1mara en tercera persona que se maneje con el rat\u00f3n y que tenga un seguimiento fluido. Modifica el movimiento vertical y horizontal con el rat\u00f3n, y haz que la posici\u00f3n y la vista hacia el jugador sean m\u00e1s suaves. Brinda al jugador un control visual total y una experiencia inmersiva.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br>using UnityEngine.InputSystem;<br><br>public class CameraFollow : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public Transform target;<br>&nbsp;&nbsp;&nbsp; public Vector3 offset = new Vector3(0, 3, -6);<br>&nbsp;&nbsp;&nbsp; public float followSpeed = 10f;<br>&nbsp;&nbsp;&nbsp; public float mouseSensitivity = 2f;<br>&nbsp;&nbsp;&nbsp; public float minY = -35f;<br>&nbsp;&nbsp;&nbsp; public float maxY = 60f;<br><br>&nbsp;&nbsp;&nbsp; private float currentYaw = 0f;<br>&nbsp;&nbsp;&nbsp; private float currentPitch = 10f;<br><br>&nbsp;&nbsp;&nbsp; void LateUpdate()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!enabled || target == null) return;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float mouseX = Mouse.current.delta.x.ReadValue() * mouseSensitivity;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float mouseY = Mouse.current.delta.y.ReadValue() * mouseSensitivity;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentYaw += mouseX;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentPitch -= mouseY;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentPitch = Mathf.Clamp(currentPitch, minY, maxY);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; target.rotation = Quaternion.Euler(0, currentYaw, 0);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Quaternion rotation = Quaternion.Euler(currentPitch, currentYaw, 0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vector3 desiredPosition = target.position + rotation * offset;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transform.position = Vector3.Lerp(transform.position, desiredPosition, followSpeed * Time.deltaTime);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transform.LookAt(target.position + Vector3.up * offset.y * 0.5f);<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">CoinSpawner.cs<\/h2>\n\n\n\n<p>Crea monedas de vida sobre cada dificultad.Al comenzar, identifica elementos con la etiqueta \u2018Obst\u00e1culo\u2019 y crea monedas. Automatiza las recogidas, incentivando la exploraci\u00f3n.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br><br>public class CoinSpawner : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public GameObject coinPrefab; \/\/ Asigna el prefab desde el editor<br>&nbsp;&nbsp;&nbsp; public float coinOffsetY = 1.0f; \/\/ Altura sobre el cubo<br><br>&nbsp;&nbsp;&nbsp; void Start()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GameObject&#91;] obstacles = GameObject.FindGameObjectsWithTag(\"Obstacle\");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (GameObject obstacle in obstacles)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vector3 spawnPosition = obstacle.transform.position + new Vector3(0, coinOffsetY, 0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Instantiate(coinPrefab, spawnPosition, Quaternion.identity);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Enemy.cs<\/h2>\n\n\n\n<p>Clase fundamental para oponentes con puntos de vida y fin de existencia.Reduce los puntos de vida y elimina el objeto cuando llegan a cero.Estructura consistente para todos los oponentes, permite una f\u00e1cil ampliaci\u00f3n.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br><br>public class Enemy : MonoBehaviour, IDamageable<br>{<br>&nbsp;&nbsp;&nbsp; public int maxHealth = 3;<br>&nbsp;&nbsp;&nbsp; private int currentHealth;<br><br>&nbsp;&nbsp;&nbsp; void Start()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentHealth = maxHealth;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void TakeDamage(int amount)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentHealth -= amount;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (currentHealth &lt;= 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Die();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; void Die()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Destroy(gameObject);<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">FallingPlatform.cs<\/h2>\n\n\n\n<p>Plataforma que cae al pisarla y resetea su estado. Retraso, ca\u00edda con gravedad extra y reinicio.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br><br>public class FallingPlatform : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public float fallDelay = 0.5f;<br>&nbsp;&nbsp;&nbsp; public float extraGravityMultiplier = 3f;<br><br>&nbsp;&nbsp;&nbsp; private Rigidbody rb;<br>&nbsp;&nbsp;&nbsp; private bool hasFallen = false;<br>&nbsp;&nbsp;&nbsp; private bool isInactive = false;<br>&nbsp;&nbsp;&nbsp; private Vector3 initialPosition;<br>&nbsp;&nbsp;&nbsp; private Quaternion initialRotation;<br>&nbsp;&nbsp;&nbsp; private Collider platformCollider;<br>&nbsp;&nbsp;&nbsp; private Renderer platformRenderer;<br><br>&nbsp;&nbsp;&nbsp; void Start()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb = GetComponent&lt;Rigidbody&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; platformCollider = GetComponent&lt;Collider&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; platformRenderer = GetComponent&lt;Renderer&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initialPosition = transform.position;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initialRotation = transform.rotation;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.isKinematic = true;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void TriggerFall()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!hasFallen &amp;&amp; !isInactive)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hasFallen = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Invoke(nameof(Fall), fallDelay);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; void Fall()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.isKinematic = false;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.velocity = Vector3.down * Physics.gravity.magnitude * extraGravityMultiplier;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; void OnCollisionEnter(Collision collision)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (collision.gameObject.CompareTag(\"MainPlatform\") &amp;&amp; !isInactive)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isInactive = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; platformCollider.enabled = false;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; platformRenderer.enabled = false;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.isKinematic = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void ResetPlatform()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isInactive = false;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transform.position = initialPosition;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transform.rotation = initialRotation;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.isKinematic = true;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hasFallen = false;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (platformCollider != null) platformCollider.enabled = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (platformRenderer != null) platformRenderer.enabled = true;<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">GameOverUI.cs<\/h2>\n\n\n\n<p>Controlador del men\u00fa Game Over.Reinicia o cierra el juego y permite al jugador reintentarlo o salir.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br>using UnityEngine.SceneManagement;<br><br>public class GameOverUI : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public void Retry()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SceneManager.LoadScene(\"SampleScene\");<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void QuitGame()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Application.Quit();<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">GreenCoin.cs<\/h2>\n\n\n\n<p>RMoneda que otorga vida al jugador. Comprueba si necesita vida y la otorga.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br><br>public class GreenCoin : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; private void OnTriggerEnter(Collider other)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PlayerLifeSystem playerLife = other.GetComponent&lt;PlayerLifeSystem&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (playerLife != null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (playerLife.NeedsLife())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; playerLife.GainLife();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Destroy(gameObject);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Debug.Log(\"Vidas completas, no se puede recoger la moneda.\");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">KillZone.cs<\/h2>\n\n\n\n<p>Zona letal que da\u00f1a al jugador. OnTriggerEnter quita una vida y define zonas de peligro en el nivel.<\/p>\n\n\n\n<p>using UnityEngine;<br><br>public class KillZone : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; private void OnTriggerEnter(Collider other)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (other.CompareTag(\u201cPlayer\u201d))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PlayerLifeSystem pls = other.GetComponent&lt;PlayerLifeSystem&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pls != null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pls.TakeDamage();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">MainMenu.cs<\/h2>\n\n\n\n<p>Maneja botones del men\u00fa principal.Inicia, muestra opciones y cierra con navegaci\u00f3n inicial del juego.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br>using UnityEngine.SceneManagement;<br><br>public class MainMenu : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public void StartGame()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SceneManager.LoadScene(\"YourGameScene\");<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void Options()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Debug.Log(\"Opciones\");<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void QuitGame()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Application.Quit();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Debug.Log(\"Juego cerrado\");<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">MainMenuManager.cs<\/h2>\n\n\n\n<p>Controla inicializaci\u00f3n y transici\u00f3n del men\u00fa al juego.Pausa, oculta UI y reanuda con Play.Transici\u00f3n fluida entre UI y gameplay.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br><br>public class MainMenuManager : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public CameraFollow cameraFollowScript;<br>&nbsp;&nbsp;&nbsp; public GameObject Canvas;<br><br>&nbsp;&nbsp;&nbsp; void Start()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Time.timeScale = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cursor.lockState = CursorLockMode.None;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cursor.visible = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cameraFollowScript.enabled = false;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Canvas.SetActive(false);<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void PlayGame()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Time.timeScale = 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cursor.lockState = CursorLockMode.Locked;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cursor.visible = false;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cameraFollowScript.enabled = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Canvas.SetActive(true);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gameObject.SetActive(false);<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">MovingPlatform.cs<\/h2>\n\n\n\n<p>Plataforma que se mueve entre dos puntos,Kinematic MoveBetween A-B con velocidad definida. Desaf\u00edo de sincronizaci\u00f3n y dinamismo al nivel.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br>&#91;RequireComponent(typeof(Rigidbody))]<br>public class MovingPlatform : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public Vector3 pointA = Vector3.zero;<br>&nbsp;&nbsp;&nbsp; public Vector3 pointB = new Vector3(3, 0, 0);<br>&nbsp;&nbsp;&nbsp; public float speed = 2f;<br>&nbsp;&nbsp;&nbsp; public float tolerance = 0.05f;<br><br>&nbsp;&nbsp;&nbsp; private Vector3 worldPointA, worldPointB, target, velocity;<br>&nbsp;&nbsp;&nbsp; private Rigidbody rb;<br><br>&nbsp;&nbsp;&nbsp; private void Start()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb = GetComponent&lt;Rigidbody&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.isKinematic = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.interpolation = RigidbodyInterpolation.Interpolate;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; worldPointA = transform.position + pointA;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; worldPointB = transform.position + pointB;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; target = worldPointB;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; private void FixedUpdate()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vector3 current = rb.position;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vector3 newPos = Vector3.MoveTowards(current, target, speed * Time.fixedDeltaTime);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; velocity = (newPos - current) \/ Time.fixedDeltaTime;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb.MovePosition(newPos);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (Vector3.Distance(newPos, target) &lt; tolerance)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; target = target == worldPointA ? worldPointB : worldPointA;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public Vector3 GetVelocity() =&gt; velocity;<br><br>#if UNITY_EDITOR<br>&nbsp;&nbsp;&nbsp; private void OnDrawGizmosSelected()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vector3 a = Application.isPlaying ? worldPointA : transform.position + pointA;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vector3 b = Application.isPlaying ? worldPointB : transform.position + pointB;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Gizmos.color = Color.green; Gizmos.DrawSphere(a, 0.1f);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Gizmos.color = Color.red;&nbsp;&nbsp; Gizmos.DrawSphere(b, 0.1f);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Gizmos.color = Color.yellow;Gizmos.DrawLine(a, b);<br>&nbsp;&nbsp;&nbsp; }<br>#endif<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">PlayerController.cs<\/h2>\n\n\n\n<p>Control principal de jugador: movimiento, salto, ataque y plataforma. Input System, animaciones, detecci\u00f3n OverlapSphere y TriggerFall.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br>using UnityEngine.InputSystem;<br><br>&#91;RequireComponent(typeof(CharacterController))]<br>public class PlayerController : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public float speed = 5f; public float gravity = -9.81f; public float jumpHeight = 2f; public float speedSmooth = 10f;<br>&nbsp;&nbsp;&nbsp; public float attackRange = 1.5f; public int attackDamage = 1; public LayerMask enemyLayer;<br><br>&nbsp;&nbsp;&nbsp; private CharacterController controller; private PlayerControls inputActions;<br>&nbsp;&nbsp;&nbsp; private Vector2 moveInput; private Vector3 velocity; private bool jumpRequested = false;<br>&nbsp;&nbsp;&nbsp; private Animator animator; private float currentAnimSpeed = 0f;<br><br>&nbsp;&nbsp;&nbsp; private void Awake()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; controller = GetComponent&lt;CharacterController&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputActions = new PlayerControls();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; animator = GetComponentInChildren&lt;Animator&gt;();<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; private void OnEnable()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputActions.Player.Enable();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputActions.Player.Move.performed += ctx =&gt; moveInput = ctx.ReadValue&lt;Vector2&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputActions.Player.Move.canceled += ctx =&gt; moveInput = Vector2.zero;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputActions.Player.Jump.performed += ctx =&gt; jumpRequested = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputActions.Player.Attack.performed += ctx =&gt; animator.SetTrigger(\"Attack\");<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void PerformAttack()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Collider&#91;] hits = Physics.OverlapSphere(transform.position, attackRange, enemyLayer);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (Collider c in hits)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.GetComponent&lt;IDamageable&gt;()?.TakeDamage(attackDamage);<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; private void Update()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool isGrounded = controller.isGrounded;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; animator.SetBool(\"isGrounded\", isGrounded);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float targetSpeed = new Vector2(moveInput.x, moveInput.y).magnitude;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentAnimSpeed = Mathf.Lerp(currentAnimSpeed, targetSpeed, speedSmooth * Time.deltaTime);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; animator.SetFloat(\"Speed\", currentAnimSpeed);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; animator.SetBool(\"isRunning\", targetSpeed &gt; 0.1f);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isGrounded)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (velocity.y &lt; 0) velocity.y = -2f;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (jumpRequested)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jumpRequested = false;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; animator.ResetTrigger(\"Jump\"); animator.SetTrigger(\"Jump\");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; velocity.y += gravity * Time.deltaTime;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vector3 move = transform.right * moveInput.x + transform.forward * moveInput.y;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; controller.Move((move * speed + Vector3.up * velocity.y) * Time.deltaTime);<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; private void OnControllerColliderHit(ControllerColliderHit hit)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hit.gameObject.GetComponent&lt;FallingPlatform&gt;()?.TriggerFall();<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; private void OnDrawGizmosSelected()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Gizmos.color = Color.red;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Gizmos.DrawWireSphere(transform.position, attackRange);<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">PlayerLifeSystem.cs<\/h2>\n\n\n\n<p>Sistema de puntos de vida del jugador con respawn y Game Over.Ca\u00eddas, ca\u00edda fuera del mapa, UI de vidas, reinicio plataformas. Control del ciclo de vida del jugador y gesti\u00f3n de errores en ca\u00edda.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using System.Collections;<br>using UnityEngine;<br>using UnityEngine.SceneManagement;<br><br>public class PlayerLifeSystem : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public int maxLives = 3; public Transform respawnPoint; public float minFallHeight = 2.357f; public float deathYLimit = -20f;<br>&nbsp;&nbsp;&nbsp; public UIManager uiManager;<br><br>&nbsp;&nbsp;&nbsp; private int currentLives; private float highestY; private bool isFalling = false; private bool wasGroundedLastFrame = true; private bool lifeLostThisFall = false;<br>&nbsp;&nbsp;&nbsp; private CharacterController controller; private GameObject lastGroundedObject;<br>&nbsp;&nbsp;&nbsp; public Vector3 velocity = Vector3.zero;<br>&nbsp;&nbsp;&nbsp; public int CurrentLives =&gt; currentLives;<br><br>&nbsp;&nbsp;&nbsp; void Start()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; controller = GetComponent&lt;CharacterController&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (controller == null || respawnPoint == null) { enabled = false; return; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentLives = maxLives; highestY = transform.position.y;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uiManager?.UpdateLives(currentLives);<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; void Update()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool isGrounded = controller.isGrounded; float currentY = transform.position.y;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!isGrounded)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (currentY &gt; highestY) highestY = currentY;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!isFalling) { isFalling = true; lifeLostThisFall = false; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isGrounded &amp;&amp; !wasGroundedLastFrame &amp;&amp; isFalling)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float fallDistance = highestY - currentY;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RaycastHit hit; if (Physics.Raycast(transform.position, Vector3.down, out hit, 2f)) lastGroundedObject = hit.collider.gameObject;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fallDistance &gt;= minFallHeight &amp;&amp; !lifeLostThisFall &amp;&amp; lastGroundedObject.CompareTag(\"MainPlatform\"))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { LoseLife(); lifeLostThisFall = true; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResetFallTracking();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (transform.position.y &lt; deathYLimit &amp;&amp; !lifeLostThisFall) { LoseLife(); lifeLostThisFall = true; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wasGroundedLastFrame = isGrounded;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; void OnControllerColliderHit(ControllerColliderHit hit) { if (controller.isGrounded) lastGroundedObject = hit.gameObject; }<br><br>&nbsp;&nbsp;&nbsp; void LoseLife()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentLives--; uiManager?.UpdateLives(currentLives);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (currentLives &gt; 0) Respawn(); else GameOver();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; void Respawn()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; velocity = Vector3.zero; controller.enabled = false; transform.position = respawnPoint.position; controller.enabled = true; ResetFallTracking();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var p in FindObjectsByType&lt;FallingPlatform&gt;(FindObjectsSortMode.None)) p.ResetPlatform();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; void GameOver() { SceneManager.LoadScene(\"GameOverScene\"); }<br>&nbsp;&nbsp;&nbsp; void ResetFallTracking() { highestY = transform.position.y; isFalling = false; }<br>&nbsp;&nbsp;&nbsp; public bool NeedsLife() =&gt; currentLives &lt; maxLives;<br>&nbsp;&nbsp;&nbsp; public void GainLife() { if (NeedsLife()) { currentLives++; uiManager?.UpdateLives(currentLives); } }<br>&nbsp;&nbsp;&nbsp; public void TakeDamage() { LoseLife(); }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Roller.cs<\/h2>\n\n\n\n<p>Rodillo que da\u00f1a al jugador y se destruye al finalizar recorrido.Detecta triggers y colisiones con el Player.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br><br>public class Roller : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public bool HasLeftPlatform { get; private set; } = false;<br>&nbsp;&nbsp;&nbsp; public bool IsDone { get; private set; } = false;<br>&nbsp;&nbsp;&nbsp; public bool HasTouchedPlazaRoll { get; private set; } = false;<br><br>&nbsp;&nbsp;&nbsp; void OnTriggerEnter(Collider other)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (other.CompareTag(\"PlazaRoll\"))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HasTouchedPlazaRoll = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (other.CompareTag(\"RollerEnd\"))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HasLeftPlatform = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IsDone = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Destroy(gameObject);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; void OnCollisionEnter(Collision collision)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (collision.gameObject.CompareTag(\"Player\"))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; collision.gameObject.GetComponent&lt;PlayerLifeSystem&gt;()?.TakeDamage();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">RollerSpawner.cs<\/h2>\n\n\n\n<p>Generador alternado de rodillos en puntos izquierdo\/derecho. Controla spawn y evita repeticiones.Ritmo de obst\u00e1culos y variabilidad.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br>using System.Collections;<br><br>public class RollerSpawner : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public GameObject&#91;] rollerPrefabs;<br>&nbsp;&nbsp;&nbsp; public Transform leftSpawnPoint;<br>&nbsp;&nbsp;&nbsp; public Transform rightSpawnPoint;<br>&nbsp;&nbsp;&nbsp; public float spawnDelay = 1.5f;<br><br>&nbsp;&nbsp;&nbsp; private bool spawnLeftNext = true;<br>&nbsp;&nbsp;&nbsp; private int lastPrefabIndex = -1;<br><br>&nbsp;&nbsp;&nbsp; void Start()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StartCoroutine(SpawnRollersAlternately());<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; IEnumerator SpawnRollersAlternately()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (true)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Transform sp = spawnLeftNext ? leftSpawnPoint : rightSpawnPoint;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int idx = GetRandomPrefabIndex();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GameObject roller = Instantiate(rollerPrefabs&#91;idx], sp.position, Quaternion.identity);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Roller rs = roller.GetComponent&lt;Roller&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (rs != null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yield return new WaitUntil(() =&gt; rs.HasTouchedPlazaRoll);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yield return new WaitForSeconds(spawnDelay);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spawnLeftNext = !spawnLeftNext;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; int GetRandomPrefabIndex()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int idx;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do { idx = Random.Range(0, rollerPrefabs.Length); }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (idx == lastPrefabIndex);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastPrefabIndex = idx;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return idx;<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">UIManager.cs<\/h2>\n\n\n\n<p>Gestiona UI de vidas.Actualiza contador en pantalla.Feedback inmediato al jugador sobre sus vidas restantes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br>using TMPro;<br><br>public class UIManager : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public TextMeshProUGUI livesText;<br><br>&nbsp;&nbsp;&nbsp; public void UpdateLives(int currentLives)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; livesText.text = \"Vidas: \" + currentLives;<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">VictoryTrigger.cs<\/h2>\n\n\n\n<p>Detecta llegada a meta y activa UI de victoria<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br><br>public class VictoryTrigger : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public VictoryUIManager victoryUI;<br><br>&nbsp;&nbsp;&nbsp; void OnCollisionEnter(Collision collision)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (collision.gameObject.CompareTag(\"Player\"))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; victoryUI.ShowVictoryScreen();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">VictoryUIManager.cs<\/h2>\n\n\n\n<p>Controla panel de victoria y navegaci\u00f3n entre niveles.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using UnityEngine;<br>using UnityEngine.SceneManagement;<br><br>public class VictoryUIManager : MonoBehaviour<br>{<br>&nbsp;&nbsp;&nbsp; public GameObject victoryPanel;<br><br>&nbsp;&nbsp;&nbsp; void Start()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (victoryPanel != null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; victoryPanel.SetActive(false);<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void ShowVictoryScreen()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (victoryPanel != null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Time.timeScale = 0f;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; victoryPanel.SetActive(true);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void RetryLevel()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Time.timeScale = 1f;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; public void NextLevel()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Time.timeScale = 1f;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int nextSceneIndex = SceneManager.GetActiveScene().buildIndex + 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nextSceneIndex &lt; SceneManager.sceneCountInBuildSettings)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SceneManager.LoadScene(nextSceneIndex);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Debug.Log(\"\u00a1No hay m\u00e1s niveles!\");<br>&nbsp;&nbsp;&nbsp; }<br>}<br><br><br><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Video explicaci\u00f3n <\/h2>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"2025 05 29 22 28 40\" width=\"800\" height=\"450\" src=\"https:\/\/www.youtube.com\/embed\/j7Lq0_ZDTHE?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\u00bfC\u00f3mo se juega SpeedAndJump?<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83c\udfaf&nbsp;<strong>Objetivo principal:<\/strong><\/h4>\n\n\n\n<p>Sobrevivir y avanzar por un entorno de plataformas mientras esquivas peligros, derrotas enemigos (como abejas), recoges monedas de vida y llegas al final del nivel (zona de victoria).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd79\ufe0f&nbsp;<strong>Controles del jugador:<\/strong><\/h3>\n\n\n\n<p><strong>Movimiento:<\/strong>&nbsp;Con teclado (probablemente con&nbsp;<code>WASD<\/code>&nbsp;o flechas).<\/p>\n\n\n\n<p><strong>C\u00e1mara:<\/strong>&nbsp;Controlada con el rat\u00f3n (rotaci\u00f3n horizontal y vertical).<\/p>\n\n\n\n<p><strong>Saltar:<\/strong>&nbsp;Presionar una tecla (probablemente&nbsp;<code>Espacio<\/code>) para realizar un salto.<\/p>\n\n\n\n<p><strong>Atacar:<\/strong>&nbsp;Usar una tecla (probablemente&nbsp;<code>Click izquierdo<\/code>&nbsp;o&nbsp;<code>Ctrl<\/code>) para ejecutar una animaci\u00f3n de ataque que da\u00f1a enemigos cercanos.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2764\ufe0f&nbsp;<strong>Sistema de vidas:<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Empiezas con\u00a0<strong>3 vidas<\/strong>.<\/li>\n\n\n\n<li>Pierdes una vida si:\n<ul class=\"wp-block-list\">\n<li>Caes desde una altura muy alta.<\/li>\n\n\n\n<li>Te caes del mapa.<\/li>\n\n\n\n<li>Te ataca un enemigo.<\/li>\n\n\n\n<li>Entras en una zona letal (<code>KillZone<\/code>).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Puedes\u00a0<strong>recuperar vidas<\/strong>\u00a0recogiendo monedas verdes (<code>GreenCoin<\/code>), pero\u00a0<strong>solo si no tienes el m\u00e1ximo<\/strong>.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udc1d&nbsp;<strong>Enemigos:<\/strong><\/h3>\n\n\n\n<p>Hay&nbsp;<strong>abejas voladoras<\/strong>&nbsp;que siguen al jugador y atacan cuando est\u00e1n cerca.<\/p>\n\n\n\n<p>Al recibir da\u00f1o, el jugador pierde una vida.<\/p>\n\n\n\n<p>Las abejas se comportan de forma din\u00e1mica: siguen, flotan y atacan.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u26a0\ufe0f&nbsp;<strong>Obst\u00e1culos y plataformas:<\/strong><\/h3>\n\n\n\n<p>Hay&nbsp;<strong>plataformas m\u00f3viles<\/strong>&nbsp;y otras que&nbsp;<strong>caen al pisarlas<\/strong>, aumentando el desaf\u00edo.<\/p>\n\n\n\n<p>Rodillos que se mueven y pueden da\u00f1ar al jugador (<code>Roller<\/code>).<\/p>\n\n\n\n<p>Zona letal (<code>KillZone<\/code>) que mata autom\u00e1ticamente al jugador si entra.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\udde9&nbsp;<strong>Recursos y recolecci\u00f3n:<\/strong><\/h3>\n\n\n\n<p><strong>Monedas de vida<\/strong>&nbsp;sobre los obst\u00e1culos. Aparecen autom\u00e1ticamente al inicio (<code>CoinSpawner<\/code>).<\/p>\n\n\n\n<p><strong>Sistema de UI<\/strong>&nbsp;que te muestra cu\u00e1ntas vidas te quedan.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfc1&nbsp;<strong>Fin del juego:<\/strong><\/h3>\n\n\n\n<p><strong>Ganas<\/strong>&nbsp;si llegas al final del nivel y activas la zona de victoria (<code>VictoryTrigger<\/code>).<\/p>\n\n\n\n<p><strong>Pierdes<\/strong>&nbsp;si se te acaban las vidas y se carga la escena de Game Over (<code>GameOverScene<\/code>).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Video Juego SpeedAndJump<\/h2>\n\n\n\n<figure class=\"wp-block-embed is-type-rich is-provider-gestor-del-servicio wp-block-embed-gestor-del-servicio\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/youtube.com\/watch?v=j7Lq0_ZDTHE%3Ffeature%3Doembed\n<\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Cr\u00e9ditos<\/strong><\/h2>\n\n\n\n<p><strong>Autor:<\/strong>&nbsp;<a href=\"https:\/\/niixer.com\/?page_id=68069&amp;preview=true&amp;_thumbnail_id=68075\">Diana Marcela Sanchez Sanchez<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/niixer.com\/?page_id=68069&amp;preview=true&amp;_thumbnail_id=68075\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Editor:<\/strong>&nbsp;Carlos Iv\u00e1n Pinz\u00f3n Romero<\/a><\/p>\n\n\n\n<p><strong>C\u00f3digo:<\/strong>&nbsp;UCMV-9 \u2013 Modelado 3D y Videojuegos<\/p>\n\n\n\n<p><strong>Universidad<\/strong>:&nbsp;<a href=\"https:\/\/www.ucentral.edu.co\/\">Universidad central<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Referencia<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">Unity Technologies. (2025). <em>Software de desarrollo de juegos: Crea juegos 2D y 3D<\/em>. Unity. <a class=\"\" href=\"https:\/\/unity.com\/es\/games\">https:\/\/unity.com\/es\/games<\/a><br><br><br>Unity Technologies. (s.f.). Gu\u00eda de inicio r\u00e1pido para el desarrollo de juegos 3D. Recuperado el 23 de mayo de 2025, de https:\/\/docs.unity3d.com\/6000.1\/Documentation\/Manual\/Quickstart3D.html<br><br><br>Unity Technologies. (2025). Unity Asset Store: The Best Assets for Game Making. Unity. https:\/\/assetstore.unity.com\/<br><br><br>Pixabay. (s.f.). Efectos de sonido de bosque horror - b\u00fasqueda. https:\/\/pixabay.com\/es\/sound-effects\/search\/bosque-horror\/ <br><br><br>Unity Technologies. (2022). Tiling Textures - 3D Microgame Add-Ons. AssetStore Unity. https:\/\/assetstore.unity.com\/packages\/2d\/textures-materials\/tiling-textures-3d-microgame-add-ons-174461<br><br><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Este documento describe el proceso de desarrollo del videojuego&nbsp;SpeedAndJump, un proyecto en Unity dise\u00f1ado en perspectiva de primera persona. El juego consiste en guiar a un personaje a trav\u00e9s de diversos retos, plataformas m\u00f3viles, enemigos y trampas, con el objetivo final de alcanzar un castillo. Durante el desarrollo se implementaronSeguir Leyendo<\/p>\n","protected":false},"author":1925,"featured_media":68075,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[30],"tags":[],"class_list":["post-68145","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-niixer"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final &#8211; Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos<\/title>\n<meta name=\"description\" content=\"En Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos encuentra los mejores contenidos del mundo de la tecnolog\u00eda | Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final &#8211; Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos\" \/>\n<meta property=\"og:description\" content=\"En Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos encuentra los mejores contenidos del mundo de la tecnolog\u00eda | Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final\" \/>\n<meta property=\"og:url\" content=\"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/\" \/>\n<meta property=\"og:site_name\" content=\"Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/niixer\/\" \/>\n<meta property=\"article:published_time\" content=\"2025-05-31T13:47:20+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-05-31T14:40:19+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/Captura-de-pantalla-2025-05-28-211149.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1071\" \/>\n\t<meta property=\"og:image:height\" content=\"601\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Diana Sanchez\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Diana Sanchez\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutos\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final &#8211; Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos","description":"En Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos encuentra los mejores contenidos del mundo de la tecnolog\u00eda | Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/","og_locale":"es_ES","og_type":"article","og_title":"Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final &#8211; Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos","og_description":"En Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos encuentra los mejores contenidos del mundo de la tecnolog\u00eda | Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final","og_url":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/","og_site_name":"Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos","article_publisher":"https:\/\/www.facebook.com\/niixer\/","article_published_time":"2025-05-31T13:47:20+00:00","article_modified_time":"2025-05-31T14:40:19+00:00","og_image":[{"width":1071,"height":601,"url":"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/Captura-de-pantalla-2025-05-28-211149.png","type":"image\/png"}],"author":"Diana Sanchez","twitter_card":"summary_large_image","twitter_misc":{"Escrito por":"Diana Sanchez","Tiempo de lectura":"15 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/#article","isPartOf":{"@id":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/"},"author":{"name":"Diana Sanchez","@id":"https:\/\/niixer.com\/#\/schema\/person\/95f70eb10a81e761e08e2817ab7b8fcf"},"headline":"Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final","datePublished":"2025-05-31T13:47:20+00:00","dateModified":"2025-05-31T14:40:19+00:00","mainEntityOfPage":{"@id":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/"},"wordCount":2465,"publisher":{"@id":"https:\/\/niixer.com\/#organization"},"image":{"@id":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/#primaryimage"},"thumbnailUrl":"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/Captura-de-pantalla-2025-05-28-211149.png","articleSection":["Niixer"],"inLanguage":"es"},{"@type":"WebPage","@id":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/","url":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/","name":"Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final &#8211; Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos","isPartOf":{"@id":"https:\/\/niixer.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/#primaryimage"},"image":{"@id":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/#primaryimage"},"thumbnailUrl":"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/Captura-de-pantalla-2025-05-28-211149.png","datePublished":"2025-05-31T13:47:20+00:00","dateModified":"2025-05-31T14:40:19+00:00","description":"En Portal de noticias de tecnolog\u00eda, Realidad Virtual, Aumentada y Mixta, Videojuegos encuentra los mejores contenidos del mundo de la tecnolog\u00eda | Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final","breadcrumb":{"@id":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/#primaryimage","url":"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/Captura-de-pantalla-2025-05-28-211149.png","contentUrl":"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/Captura-de-pantalla-2025-05-28-211149.png","width":1071,"height":601,"caption":"Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final"},{"@type":"BreadcrumbList","@id":"https:\/\/niixer.com\/index.php\/2025\/05\/31\/desarrollo-del-videojuego-speedandjump-en-unity-superacion-de-retos-hasta-el-castillo-final\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/niixer.com\/"},{"@type":"ListItem","position":2,"name":"Desarrollo del Videojuego \u201cSpeedAndJump\u201d en Unity \u2013 Superaci\u00f3n de Retos hasta el Castillo Final"}]},{"@type":"WebSite","@id":"https:\/\/niixer.com\/#website","url":"https:\/\/niixer.com\/","name":"Portal de noticias de tecnolog\u00eda, ciencia, Android, iOS, Realidad Virtual, Aumentada y Mixta, Videojuegos, computadores, todo lo mas reciente en tecnolog\u00eda","description":"Portal de noticias de tecnolog\u00eda","publisher":{"@id":"https:\/\/niixer.com\/#organization"},"alternateName":"Niixer","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/niixer.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/niixer.com\/#organization","name":"Niixer","alternateName":"Niixer.com","url":"https:\/\/niixer.com\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/niixer.com\/#\/schema\/logo\/image\/","url":"https:\/\/niixer.com\/wp-content\/uploads\/2022\/08\/logo-niixer-sin-fondo-1.png","contentUrl":"https:\/\/niixer.com\/wp-content\/uploads\/2022\/08\/logo-niixer-sin-fondo-1.png","width":140,"height":140,"caption":"Niixer"},"image":{"@id":"https:\/\/niixer.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/niixer\/","https:\/\/www.instagram.com\/niixer.tecnologia\/"]},{"@type":"Person","@id":"https:\/\/niixer.com\/#\/schema\/person\/95f70eb10a81e761e08e2817ab7b8fcf","name":"Diana Sanchez","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/secure.gravatar.com\/avatar\/9fb1e0872b11aa0547c77e76bb3e2f6adb485060c99e9f374604c9c99884a785?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/9fb1e0872b11aa0547c77e76bb3e2f6adb485060c99e9f374604c9c99884a785?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9fb1e0872b11aa0547c77e76bb3e2f6adb485060c99e9f374604c9c99884a785?s=96&d=mm&r=g","caption":"Diana Sanchez"},"sameAs":["http:\/\/www.nixer.com"],"url":"https:\/\/niixer.com\/index.php\/author\/dsanchezs10\/"}]}},"jetpack_featured_media_url":"https:\/\/niixer.com\/wp-content\/uploads\/2025\/05\/Captura-de-pantalla-2025-05-28-211149.png","_links":{"self":[{"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/posts\/68145","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/users\/1925"}],"replies":[{"embeddable":true,"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/comments?post=68145"}],"version-history":[{"count":2,"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/posts\/68145\/revisions"}],"predecessor-version":[{"id":68149,"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/posts\/68145\/revisions\/68149"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/media\/68075"}],"wp:attachment":[{"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/media?parent=68145"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/categories?post=68145"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/niixer.com\/index.php\/wp-json\/wp\/v2\/tags?post=68145"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}