Siguiente Vamos a hacer que el enemigo se spamear aleatoriamente en diferentes partes de la pantalla.
Evidentemente, si cuando tiras al enemigo se cae, todavía va para arriba, pero eso forma parte del
Game Over.
Todavía no hemos ido a por ellos.
Estamos sólo con la fase de enemigos, así que tenemos un enemigo, pero con un enemigo no vamos a ningún
lado.
Queremos una colección de enemigos.
Colección de enemigos igual.
Por tanto, carpeta Faithfull, le llamáis app y AFAPs.
Vamos a arrastrar el bicho este el enemigo.
Acordaros cuando lo arrastra.
Es que por defecto tiene unas coordenadas que es de donde lo habeis arrastrado.
Recomendación personal los resetearse para que siempre esté el cero cero cero vuestro Griffa y de hecho
el que tenéis en medio de la pantalla.
Ahora mismo ya ni pincha ni corta.
O sea, que haya un enemigo al inicio también, pero como nos vamos a instancias dinámicamente, este
lo podéis mandar a freír espárragos.
Entonces nos lo cargamos.
Quién va a ser el encargado de crear enemigos?
Pues un manager, un manager que podría ser el manager o podría ser algo más específico, como un spawn
manager hecho.
En nuestro caso va a ser un spawn manager por si queremos tener separados la lógica de Spaulding de
la lógica del gameplay en sí mismo.
Vale, entonces ya sabéis como va esto lo hemos hecho varias veces.
Botón derecho creáis un objeto vacío.
Este objeto vacío lo llamáis Nogai Mog, sino que Spawn Mãnager como es vacío e invisible, lo ahí es
donde os de la gana, tipicamente todos los Mãnager siempre se van por defecto a la cero cero cero.
Así todos estaban siempre en medio de la escena.
Manías mías y en la carpeta de los scripts vamos a crear un script homónimo.
Sillar script.
Le vamos a llamar Spawn Manager.
Todo junto con la S y la M mayúsculas.
Con ese script es palmauna.
Hacemos dos cosas.
La primera es dárselo al objeto Spawn manager de la jerarquía para que tenga el script con la funcionalidad
que ahora vamos a implementar.
Y la segunda es doble clic para abrirlo en el editor.
Ahora hay dos formas de actuar.
Ya hemos hecho esto varias veces.
Si solo hay un tipo de enemigo, os basta una variable Magic.
Si queréis que haya 6, 7, 8, 10 tipos de enemigos, necesitáis un monje.
Corchetes Os acordáis?
En mi caso, a ver cómo sólo van a ser bolas.
Voy a colocar solo 1 públic gameshop y lo voy a llamar en el prefacio de mi tripa.
Si luego queréis 2 tipos de enemigos, tres tipos de enemigos, diez tipos de enemigos, bolas más grandes,
más pequeñas, que pesen más, que pesen menos, con más fuerza, con menos fuerza, cambiáis este Joinville
por corchetes y haceís que aleatoriamente se espanté uno u otro.
Así le daría mucha más variedad y también mayor dificultad al propio videojuego.
Entonces este es el objeto que sea más pavonearse y de momento vamos a hacerlo fácil en el estar.
Nuestro manager va a invocar el método Instantly para instancias s n mi prima Koma en la posición New
Vector 3 por una posición de Dentrodel del ring ring mientras los mantengas en el cuadrado de menos
nueve nueve seis cero cero cero es el centro y el nueve nueve nueve nueve serían los extremos máximos
en X y Z.
Aquí en este caso de poner a piñón de momento el cero cero cinco por poner uno a piñón y la rotación.
Recordad que siempre que hacéis un instante hay que decirle dónde y con qué rotación.
La propia rotación que ya tenga la bola al inicio es una bola.
O sea, por mucho que la Rotax seguirá siendo una bola, tú si quieres meter tu dragón aquí, es todavía
más importante que el segundo parámetro sea mi punto Transform Punto Rotation para que así herede la
rotación del modelo 3D que tú mismo has generado.
Vale, si no, pues a lo mejor tu prefacios estaría de una forma o instancias de otra y te podría salir
el Dragon tuerto, basicamente.
Entonces guardamos esta cosa.
De momento la instancia como veis la opinión en una posicion determinada con una rotación específica
de un objeto concreto, no hay nada de aleatoriedad.
Me puedo cargar el aboitiz porque la función del manager sólo tiene sentido al inicio de momento e irnos
a nuestro editor porque hay que hacer una cosa cual nuestro manager tiene una caja vacía que está esperando
un game object, ese que hay mov que vamos a arrastrar va a ser precisamente el que está en la carpeta
de apps, que es nuestro enemigo y para comprobar que funciona es muy fácil.
Le dais al play y en la posición cero cero cinco debería salir una bola de color rojo.
La veis, aparece y viene a por mí.
Viene tan lento porque soy idiota y lo he dejado con un peso terriblemente grande de 100 kilos.
Vale, lo voy a poner dos kilos de momento y así se moverá más rápidamente.
Fijaros que al inicio no hay absolutamente nada y es cuando aparece que empieza a darme hostias pa arriba
o abajo.
Lo veis chip entonces?
Fase número 1 que se es Pawnee, el objeto conseguido.
Fase número 2.
Vamos a hacer que la posición sea aleatoria.
Como os he dicho, si os imaginais un cuadrado desde el punto menos 9 9 9 9, básicamente es el área
comprendida en el cuadrado que quedaría inscrito dentro del medio.
Así que de lo que tengo aquí hay dos coordenadas que pueden cambiar, que son la X y la Z, y la sigo
manteniendo en cero por razones obvias para que esté a la altura original, pero la X y la Y la Z van
a ser aleatorias.
Lo mismo que ya hemos dicho antes.
Yo podría hacer que este 0 fuera el valor aleatorio, que estafetas fuera el valor aleatorio y quedar
aquí como un crack, haciéndolo todo en una línea, complicando vuestra legibilidad del código.
No lo voy a hacer.
Mejor creamos dos variables float spawn.
Position X y Flow Spawn Position Z.
Recordad que la Isshin puestero.
De modo que los valores aleatorios pasan a ser Spawn, X y Z, respectivamente.
Aquí me está dando un error porque no lo sé inicializar lo vamos a hacer que el valor sea aleatorio
entre menos 9 y 9 por lo que os he comentado antes, así que en este caso lo que voy a hacer es arriba,
definir una propiedad privada Flower Power Ranger, que será 9 de lo que os he comentado antes para
no ponerla a piñón.
Es decir, yo aquí podría escribir Random Raids de menos 9 a 9, pero el día de mañana hacemos el rig
más grande o el juego más difícil.
Por ejemplo, necesitaré cambiar este spawn reimos.
Así que en este caso lo vamos a dinamizar y el spawn position X será igual a rando punto reintsch entre
menos Spawn, Reigns y Spawn Range.
Fijaros que escribir esto es totalmente sinónimo a poner esto entre menos 9 y 9, con la diferencia
que entre menos 9 9 los valores están rodeados, están escritos a piñón en el código y estos son dinámicos.
Es decir, el día de mañana quieres que el rango no sea 9, sino que quieres que sea 8 y medio.
Vienes aquí y lo cambias de listos.
Vale.
De hecho, de momento lo dejamos en 9.
Y lo mismo con el spawn z, otro valor aleatorio, otro random entre menos spawn frangie y más spawn
range.
Y ahora lo que vais a obtener gracias a esto es que la posición en la que haceis la instancia ación
es aleatoria.
De hecho, ahora podéis ver que incluso la propia posición es difícil de leer porque ahora es un vector.
3.
Spawn bosteros a un boceta.
Este es el caso perfecto en el que todavía añadiría otra variable, otro vector 3 con random bots posición
aleatoria igual a lo que antes estaba dentro del instante y así queda en una variable externalizado.
Y ahora, de hecho, vuelvo a ser capaz primero de tenerlo todo en función de variables.
Ya no tengo ningún valor por ahí en medio.
Y de hecho, me vuelve a caber en una línea que era mi objetivo que cupiera todo fuera bonito.
Fácil de leer.
Fijaros que ahora esto cualquiera que lleve dos días en Unity lo entiende.
Generamos un valor aleatorio en X que irá desde menos Rains.
Generamos un valor aleatorio en Z que irá desde menos 30 sparrings.
Con esos dos valores aleatorios generamos una posición aleatoria cuya altura es cero y instancias dos,
el del enemigo en esta posición aleatoria y con la rotación exacta que tuviera el enemy grifa.
De hecho, fijaros que tal cual lo tengo así, las tres primeras líneas de código tienen una funcionalidad
cual generar una oposición aleatoria válida, de hecho esto quiere decir que tal cual lo tengo aquí
por si mismos.
Estas tres líneas de código tienen personalidad propia, tienen una función que pueden llevar a cabo,
que es la de generar una posición aleatoria y esto va a pasar muchas veces.
De hecho, ya me ha salido muchas veces lo de obtener el movimiento horizontal y vertical del controller.
El mover, desplazar, rotar, aplicar una fuerza.
Son operaciones de 2 3 4 5 líneas de código que siempre van juntitos de la mano y cuya funciones es
una de estas que he dicho llevar a cabo una de esas tareas.
Qué quiere decir esto?
Quiere decir que el código que utilizáis para llevar a cabo una tarea en lugar de ir a piñón dentro
del estar dentro de la deuda?
Además, conviene que vaya en una función independiente por dos motivos.
Claridad, legibilidad, que se pueda leer de forma mucho más fácil.
Lo que decíamos antes y reutilización que el día que necesitáis volver a generar un número aleatorio.
Pues esa función ya cumple.
Todo lo que necesita es eso.
Son prácticas de muy buena programación y que van enfocadas a que sobretodo sigamos unos estándares
la programación.
El problema que me he encontrado con la gente es que no es como aprender un idioma o no, es como aprender
matemáticas o no, es como aprender algo que sigue unas reglas pautadas que sigues los pasos y siempre
llegas al mismo resultado.
La programación mezcla parte de eso, pero también parte de calidad del código e incluso gusto arte.
Incluso a veces de cómo lo estructuras para que te quede bonito.
Es una muy buena práctica.
Es estas tres líneas de código que al final lo que hacen es ensuciarme.
El estar las voy a separar en una función independiente, una función que la voy a hacer privada, porque
solo al manager le importa cómo se generan esas posiciones aleatorias.
Hasta ahora todas las funciones que hemos creado venían marcadas con esta palabra llamadas VoIP.
Qué no devolvían nada?
Este es el primer ejemplo.
Donde sí que devolvemos algo, devolvemos la posición aleatoria en la que se debe generar el enemigo
aleatorio.
Por tanto, va a devolver una posición.
Las posiciones son vectores de tres coordenadas.
No lo marcaremos con la palabra bait, lo marcaremos con la palabra vector 3 porque al final de la ejecución
yo voy a crear un vector 3 y el nombre que le vamos a dar, pues a ver si esta función va a generar
una posición aleatoria.
Es Pawn.
Fijaros que de forma natural, a la que no queréis un método que tenga cincuenta mil líneas de código,
vais a necesitar introducir variables o vais a necesitar introducir métodos funciones que se encarguen
de romper el código en trocitos más pequeños.
De hecho, esto va a ser muy útil porque cuando necesitáis generar un segundo enemigo aleatorio vais
a hacerlo así cuando necesites generar un Powerade aleatorio en la escena.
Vais a poder utilizar el mismo sistema corrector.
Entonces, el código que hemos utilizado hasta ahora es correcto, funciona, pero como lo vamos a utilizar
bastante, vamos a hacer limpieza.
Esta fase de limpieza en programación recibe un nombre que es refactorización en la refactorización.
Es el arte de reestructurar vuestro código en algo que sea más legible, más utilizable y reutilizable
en el futuro.
Aquí hasta ahora esta posición aleatoria era para instancias un enemigo.
Si yo os dijera acepto un código que en una posición aleatoria instancia un potenciador, un pavorreal
a que estas tres líneas de código serían las mismas si por tanto generate.
Spawn Position es un nombre que no hace referencia a generar un enemigo o generar un pago, era o generar
una trampa genera una posición.
Punto pelota.
Entonces me traigo estas tres líneas, que son las que generan esa posición aleatoria.
Ya no van a ir en el START, sino que van a ir dentro del género de spawn position, que tiene sentido.
Y fijaros que ahora han pasado dos cosas el método estar ya no conoce posición aleatoria y el método
general spawn position.
Nosotros le hemos dicho que al final de su ejecución devuelva a un vector 3 si o no.
Si queremos devolver ese vector 3 veces que ha generado un vector 3 que es el random, necesitáis devolverlo
al final de la ejecución del método y para ello la palabra reservada que se utiliza es returned para
devolver la random que habéis generado.
Puto hickock, entonces veis que yo cada vez que ya me han generate spawn position generaría esa posición
aleatoria generar ese vector aleatorio dentro de los rangos y lo devuelvo al final.
Esto es la diferencia entre un método y un método vacío y un método que devuelve algo.
Un método veidt es un método que hace cosas, modifica cosas.
Ocurren cosas debido a ese método.
Un método que no es un método que devuelve algo es entregar un producto final.
Sería la diferencia entre que el método haga algo y que ocurran cosas, o que el método os devuelva
un producto final siempre que sea posible.
En programación nos gustara métodos que devuelvan cosas.
Por qué?
Porque si los métodos no devuelven nada, tendréis hacer una programación bastante mala.
Vale, no se sabe muy bien qué ocurre o quién es el culpable.
Qué método es el que ha hecho esto?
No lo sé.
Pasan cosas, pero como ninguno devuelve nada, nadie se hace responsable de lo que ha pasado por ahí
o es difícil saber quién es el responsable.
Si el final de un método es un producto vector 3, al final sabes que ese vector 3 que vais a utilizar
es responsabilidad de este método y que si luego falla en el futuro porque menos 9 9 es demasiado grande,
ya sabeis a quien tener que ir a echarle la culpa al que ha hecho el método de que devuelve el vector
3.
Entonces, la regla de oro para adoptar unos unas buenas prácticas de patrones de diseño y patrones
de programación sellaban es que los métodos siempre devuelvan algo siempre cuando tenías que marcar
un método como Veidt que no devuelve nada.
Estáis un paso por debajo de abogar por una buena práctica de programación.
Esto es como si os digo pues mira, al final del curso me tenéis que entregar algo de lo que habéis
aprendido.
Si me entregas un juego es algo palpable.
Es algo que yo puedo medir, que evaluar si me lo contáis de palabra.
Pues yo no lo puedo tocar, no es palpable.
Para mí es algo, es algo vacío, carente de sentido, porque cuando tú me lo has acabado de explicar
no queda un registro como tal.
Entendéis, pues, siempre que sea posible evitar que vuestras funciones vayan convey?
A ver, hay casos que van a necesitar que sea bayt, por ejemplo.
Los métodos de Junichi son todos.
Boito Pero no porque sean malos programadores es porque es un motor.
Son comportamientos y son llamados por un tercero, que es el motor que se encarga de ensamblar las
piezas.
Por eso necesita que sean vacíos, porque si cada uno devolvieran lo que.
Su el motor no podría ensamblarlo.
Pero sin embargo, vuestras funciones, vuestros métodos, siempre que sea posible evitar la palabra
bait, porque el veidt significa bueno, pues esta función va hacer algo, pero no va a quedar un registro
de qué es lo que ha generado esa función.
Y esto es válido para cualquier lenguaje de programación, no sólo válido para cesar, acostumbrarlos
que funciones vacías?
Es pereza del programador de pensar un producto final que debe devolver la función?
Vale, pues bueno, en este caso toda esta cosa devuelve una posición aleatoria.
Veis que aquí utilizaba antes mi Random Box como ahora generate spawn position ya devuelve un vector
3.
Ya devuelve una posición aleatoria a la hora de instancia.
El FAP lo podéis hacer llamando a generated spawn position.
Entonces fijaros que ahora habeis simplificado el estar que es importante.
El estar vuelve a ser legible porque cuantas líneas de código tiene el estar una instancia de esta cosa
en la posición aleatoria generada por este pavo y en esta posición aleatoria que es la del propio primo
que está distanciando.
Además, esto significa que si esto fuera un producto muy grande, el género Composition podría ser
un método que preparara.
Lo dejará, lo dejará vacío, dijera Mira R3 para Opposition Return Vector 3.0.
Esto querría decir que la posición aleatoria es la cero cero cero pa todo el mundo y pusiera un tutú.
Que alguien implemente esto.
Lo dejo para después.
El código funcionaría si se instancia haría si el cero cero cero no sería aleatoria, sería la cero
cero cero.
Pero he dejado que alguien implemente esto.
Cuando alguien viene el becario le digo a que busca los tutús, que hay un todo.
Que alguien implemente esto.
A ver, tengo que devolver un vector.
3 tiene que ser aleatorio.
Tengo estas variables bla, bla, bla, bla, bla.
Pues porque aquí lo rellena.
Lo ves tú, está listo.
Nos cargamos del todo y ya tenemos la cosa implementada.
Al final, todo lo que abogue por unas buenas prácticas de colaboración entre las diferentes personas
que forman parte de un producto de un proyecto como éste, son interesantes.
Vale, son bastante interesantes.
En particular, fijaros que el objetivo lo hemos conseguido escanear un enemigo en una zona aleatoria
de la isla.
Si yo ahora vengo aquí, después de esta transformación, de este nuevo código, el enemigo se sigue
generando aleatoriamente en una posición de la isla.
Simplemente le dais al play y cada vez la posición será diferente.
En este caso está más para allá.
Cierro, vuelvo a abrir antes ha salido por aquí, ahora sale más arriba, le vuelvo a dar al play.
Ahora saldrá de donde más abajo ves que cada vez es aleatorio y de ello se encarga el método que tenéis
aquí.
Por tanto, ya sabéis, escanear a posiciones aleatorias, factorizar el código.
Y una cosa que es interesante es la de documentar vuestros propios métodos.
Al final, por qué sabéis cómo funciona este método?
Porque yo llevo media hora hablando.
Entonces, cuando uno programa, uno no suele hablar.
Bueno, si uno suele hablar consigo mismo, porque los programadores estamos medio locos.
Pero lo más normal es que tú no te expliques a ti mismo cómo va a ir el método, si es que lo tienes
que pensar y plasmarlo en líneas de código.
Qué pasa cuando viene otra persona que tiene que trabajar en el proyecto y tiene que leer el código
que ha hecho otra persona?
Pues como no se lo hayas dejado documentado, no sabrá muy bien qué es lo que tiene que hacer.
Entonces hay una forma en Unity que es crear lo que llamamos un sumario, un resumen de una función.
Este resumen funciona a modo de documentación.
Esta documentación está bastante extendido que se haga del siguiente modo ya sabéis documentar.
De hecho, ya sabéis escribir comentarios para hacerlo es muy fácil.
Encima de la función que habéis creado escribís 3 barras de comentario y ya sabes que normalmente hemos
escrito una o dos.
Si escribís tres barras de comentario una, dos y tres, automáticamente os sale esta cosa.
Y otra cosa se llama un resumen, una documentación, un DOGC.
Este DOGC se tiene que rellenar de cierto modo, balet a saber.
Entre la etiqueta de apertura de Summary y la etiqueta de cierre de sumario se utiliza un texto legible
por humanos.
Genera una posición aleatoria dentro de la zona de juego.
Así de fácil.
A partir de aquí, si tuviera parámetros de entrada que ahora no tiene, pero si tuviera parámetros
de entrada los podríais colocar con la etiqueta para naïve y el nombre del parámetro, por ejemplo Paranoid
Bul.
Prueba el invento.
Vale, podríais poner aquí prueba.
La prueba sirve de parámetro para lo que fuera y lo que devuelve el producto final es devuelve una posición
aleatoria dentro de la zona de juego.
Qué significa esto?
Que si vosotros los documentales.
Así, el día que yo llamo al género Composition.
Ves que sale en mi comentario, genera una posición aleatoria dentro de la zona de juego, lo ves?
Acabáis de generar esta documentación, esta ayuda que venía de regalo con todos los métodos de Junípero,
pero para vuestras funciones.
Lo peor que podéis hacer es no generar la documentación para vuestras funciones.
Por qué?
Porque si yo tengo mi propio método y no lo documento, yo sé como funciona.
Yo sé para qué sirve.
Yo sé qué significa este vull prueba o qué es lo que devuelve.
Pero lo sé porque lo programado, el otro que viene, se tiene que chupar todo el código y saber qué
es lo que hace.
Por desgracia, en el mundo de la programación se documenta muy poco.
Qué quiere decir esto?
Que el día que el programador se va se va de la empresa o el día que hay un bug gordo o de malas empezáis
a sufrir las consecuencias de no documentar el caso totalmente extremo al mundo de la creación de videojuegos.
Sería un banco en un banco donde llevan 50 años con las mismas tecnologías de Los Picapiedra COBOL.
Estas cosas suele haber una persona o dos o un equipo solo para documentar y además todavía lo hacen
con papel y boli.
Es decir, hay una sala entera de archivos de libros enormes.
Esta función ha sido creado por tal programador en esta fecha.
Tiene estos parámetros de entrada, estos requisitos funcionales devuelve esto, etcétera, etcétera,
etcétera.
Entonces hay personas específicas para documentarlo todo y de hecho en un banco donde podéis entender
las razones, pues la seguridad del dinero de las personas cuando jugamos con dinero es un poco peligroso.
Normalmente algo no pasa a producción, no está disponible a menos que esté correctamente documentado
y probado.
Vale haber aquí lo he probado tres veces y ha parecido que funcionaba y que no se me caía el bicho de
la isla cuando lo generaba aleatoriamente.
Si lo probáramos más exhaustivamente, podríamos darlo como bueno, pero fijaros que aquí lo importante
que es.
Yo he creado una función, no es de Unity, no es una de no es un estarlo, es un colisionen, no es
un thriller entero, es una función creada por Juan Gabriel o la documentamos para saber exactamente
lo que hace o el día que alguien la quiere usar.
No tiene ni puñetera idea de para qué sirve.
En este caso, lo que le sobra es el bug.
Prueba, está claro, fuera y si me cargo el bug prueba que la documentación hable de un hipotético
parámetro.
Bul prueba no tiene sentido.
Pero fijaros a la que tengáis una función y la queréis documentar.
Triple barra torcida.
Pam, pam, pam.
Os pondrá una etiqueta Summary.
Hay varias más.
Hay un montón.
Podéis poner un ejemplo de uso.
Podéis poner qué tipo de excepciones lanza.
Podéis poner qué tipos de ficheros os hacen falta, todas las listas de parámetros, etcétera, etcétera.
Hay un montón que podéis colocar.
Lo veis?
Todos estos son modificadores que se utilizan a la hora de documentar vuestras propias funciones.
Así que una regla de oro para programar bien lo que os decía un poco pasar una entrevista de trabajo.
Cuando os hagan una prueba de Unity es documentarlo y documentarlos.
Esto es triple barra y escribís aquí lo que queráis.
Vale un resumen, un sumario sumarias, esos resumen si tiene parámetros de entrada, lo que os he dicho,
paramos y ponéis los nombres para nadie.
Bla, bla, bla.
Esto es el nombre del parámetro que tiene que coincidir exactamente con el que entra dentro de la función
entre paréntesis.
Y aquí una descripción de los mismos.
Esto, por cierto, es pregunta de examen de día.
Si os presentáis a título, es súper importante conocer la documentación, las razones por las cuales
se documenta y la forma correcta de documentar cada una de las cosas que pueden ocurrir, incluyendo
parámetros de entrada, valores a salida, excepciones que puedan haber, usos de ficheros externos
de información externa, etc..
Vale, perfecto.
Pues mira, ya tenemos este método y así me ha servido de excusa para comentaros lo de lo de la documentación,
que cuanto menos es divertido colocarte encima de un método que has generado tú y que te salga esto.
Por lo menos es divertido ver que no tiene parámetros tener una oposición bla, bla, bla, bla, bla,
bla bla.
Porque hasta ahora cada uno de los métodos de Junichi lo hace, lo veis?
Cada uno de ellos tenía la opción de hacerlo, pero los nuestros no?
Bueno, a partir de ahora los nuestros también.
Y de hecho, si llegamos a hacer programación genérica con tipos de datos genéricos y demás, los tipos
de datos genéricos.
Documentary Y además, creo que en el curso del conejito había un par de ejemplos de programación genérica,
las que se colocan con diamantes y la mayuscula.
Si no creo que alguno que otro nos va a hacer falta hacer en el futuro.
Preguntas no, pues.
Documental los métodos.
No hace falta estar con las Daito, el colisionen porque son eventos.
Además, ya os lo pone aquí.
Es un evento, no te tienes que preocupar de nada.
Además, está super bien documentado.
Se llama justo antes del primer Freie Tatara Tatara Tatara.
Está súper bien documentado.
Esto no hace falta, pero los vuestros propios, los que os habéis inventado, sí que es súper importante
que queden documentados.
Vale.