En este artículo vamos a ver qué es un script en programación, vamos a escribir un script simple en el bloc de notas que haga una determinada tarea y dar varios ejemplos de aplicación.
Qué es un Script en programación
En términos simples un script en programación es un documento de texto donde colocamos instrucciones u órdenes que luego serán ejecutadas por un dispositivo inteligente. Estas instrucciones estarán escritas en algún lenguaje de programación en el que se debe respetar su sintaxis para que cada instrucción pueda ser traducida a lenguaje de máquina. Además cada script será un archivo con un formato que dependerá del lenguaje en el que esté escrito.
El conjunto de todos los scripts de nuestro programa junto con otros elementos conforman el código fuente.
Un vídeo en el que creamos un script en Unity para resolver un problema
En el siguiente vídeo puedes ver el procedimiento que aplico al crear un Script, primero analizamos el problema, planteamos un estrategia para resolverlo y finalmente creamos el script con las instrucciones necesarias. El problema consiste en determinar si un número dado es par o impar, observa como antes de empezar a escribir código lo que se hace es crear una estrategia para resolver el problema, poner sobre la mesa algún fundamente teórico o datos que nos ayuden a resolver el problema, yo diría que esta es la parte más importante a la hora de programar, más importante que escribir el código en los scripts. Una vez que planteamos la estrategia procedemos a traducirla en instrucciones de código.
El campo de aplicación de la programación es muy amplio, podemos escribir programas para un sinnúmero de propósitos. Te invito a realizar el siguiente experimento para la plataforma Windows:
Vamos a abrir la aplicación Bloc de Notas o Notepad, el editor de texto de Windows de toda la vida y ecribamos las siguientes dos líneas:
timeout /t 6000 /nobreak
shutdown -h
Debería verse de la siguiente manera:
Hacemos clic en «file-save file as» o «archivo-guardar cómo» y nos aseguramos de elegir la opción «All Files (*.*)» o «Todos los archivos (*.*)«, como se observa en la figura 2. Le damos un nombre y lo terminamos con la extensión «.bat» que es la extensión Batch o lotes. Guardémoslo en el escritorio para encontrarlo rápidamente.
Archivo ejecutable con instrucciones de código
CUIDADO! SI EJECUTAS ESTE ARCHIVO TU COMPUTADORA SE APAGARÁ AUTOMÁTICAMENTE CUANDO PASEN 100 MINUTOS
Luego de seguir los pasos anteriores generamos un archivo Batch que podemos ejecutar haciendo doble clic, como se puede ver a continuación.
Al ejecutarlo se nos abre el terminal de windows indicando que se encuentra esperando una determina cantidad de tiempo que hemos indicado en nuestro Script.
Cuando se cumplan los 6000 segundos que indicamos en el Script, se ejecutará la segunda instrucción: «shutdown /h» que pondrá nuestro equipo en estado de hibernación.
Así de fácil hemos escrito un Script para que cumpla con una determinada función.
Antes tenía muchos problemas de sueño y la única forma de dormirme era escuchando algún vídeo con un volumen muy bajo, este Script que acabamos de hacer lo utilicé mucho para que la computadora no quede encendida toda la noche.
Otros ejemplos de Scripts
A continuación voy a mostrar una serie de ejemplos de Scripts que nos podemos encontrar al empezar un proyecto que involucre programación.
Juegos en Unity
Si queremos desarrollar un juego en Unity, nos vamos a encontrar con los Scripts en lenguaje C#. Es posible escribir estos Scripts en Bloc de Notas siempre que los guardemos con la extensión «.cs», pero eso sería innecesariamente complicado. Contamos con Editores que nos permiten comprobar la sintaxis, auto completar y nos hacen el trabajo más fácil.
Aplicaciones Android
Quizás estás interesado en hacer una App para Android, en ese caso una opción es utilizar el software Android Studio.
En Android Studio se escriben distintos scripts, los Scripts en lenguaje XML se utilizan para definir el diseño de nuestra aplicación y los script en lenguaje Java se utilizan para la lógica de nuestra aplicación, figuras 6 y 7 respectivamente.
Cuando estudiaba programación en la universidad usé entornos de desarrollo como Eclipse o NetBeans, en los que he escrito Scripts en Java que luego pude simular en la consola y poder analizar los resultados. Aquí dejo un ejemplo de un Script en Java utilizando el IDE NetBeans:
Entornos de programación (IDE)
Proyectos Arduino
Quizás estamos interesados en la electrónica y queremos programar un Arduino. En ese caso vamos a escribir Scripts en formato «.ino» utilizando el IDE de Arduino.
Otros ejemplos pueden ser Scripts para MatLab o SciLab, plugins para Blender, Scripts para tratar los datos en tablas de Excel, scripts para ejecutar macros y muchos otros ejemplos.
Conclusión
Los Scripts en programación son conjuntos de instrucciones escritas en algún lenguaje y que posteriormente serán ejecutadas por un dispositivo inteligente, sea un ordenador, un móvil, etcétera.
El campo de aplicación de la programación es muy extenso. Dependiendo de lo que queramos hacer vamos a tener distintas herramientas para escribir Scripts y estos estarán en distintos formatos.
Introducción
En este artículo vamos a estudiar cómo utilizar el método OnTriggerStay para detectar al personaje en una determinada región y aplicar acciones cuando eso ocurra. Concretamente vamos a hacer que las estaciones de daño y regeneración de salud afecten al personaje.
Antes de empezar te invito a ver el video que hice para resumir este artículo.
Procedimiento
Vamos a utilizar la estación «OnTriggerStay«, la cual consiste en dos aparatos con forma de detector de metal, uno rojo y otro verde y cuya función es afectar nuestro sistema de salud. Al entrar en la estación roja nuestra salud debe disminuir y con la estación verde debe aumentar.
Todos estos objetos se encuentran dentro del emptyGameObject «#5 OnTriggerStay«. Tenemos una estación de regeneración (HealthStation) y otra de daño (DamageStation).
Tanto HealthStation como DamageStation tienen asignado el mismo script, «OnTriggerStayAction«.
En el inspector podemos modificar la cantidad de salud que nos dá o nos quita a través del float «amountHealth» y podemos elegir el tipo de estación que es.
Para que las estaciones puedan hacer su trabajo es necesario que el jugador tenga algún tipo de sistema de salud al cual afectar. Esto ya viene resuelto en el GameDevLab. El GameObjectFirstPersonPlayer tiene asignado un script llamado «HealthSimple» que cuenta con las variables y métodos necesarios para proporcionarle al jugador un sistema de salud simple.
Resolución
Al abrir el script OnTriggerStayAction por primera vez nos encontramos con lo que se ve en la figura 6. Hay una región definida entre comentarios donde se sugiere redefinir el método OnTriggerStay.
¿Cómo funciona el método OnTriggerStay?
Este método está definido en la clase MonoBehaviour, por lo tanto estará presente por defecto en cualquier script nuevo que hagamos.
Se ejecuta automáticamente si un GameObject con Collider entra en la región definida por otro Collider que está en Modo Trigger. Además al menos uno de los dos GameObjects debe tener un componente RigidBody asignado.
En la figura 9 se muestra la resolución del ejercicio.
Redefinimos el método OnTriggerStay que recibe como parámetro el Collider que ha entrado en contacto con el trigger. Le damos el nombre «col» a la referencia de este Collider.
Lo que tenemos que hacer es en primer lugar determinar si el GameObject cuyo Collider entró en contacto tiene un sistema de salud al cual afectar, esto lo hacemos obteniendo la referencia de la componente HealthSimple que puede estar asignada a este GameObject.
Si el GameObject tiene sistema de salud, tendremos una componente HealthSimple, en caso contrario nuestra variable va a tener el valor null. Usamos esto como condición en la sentencia if.
Si la condición es verdadera ejecutamos el método playerIsUnderTheStation y pasamos como parámetro la referencia de HealthSimple que se encuentra en health.
Con esto ya tenemos resuelto el problema del video, a partir de ese punto la componente HealthSimple se encargará de manejar el tema de la salud.
Al entrar en la estación de daño nuestra salud comienza a mermar, si llega al valor cero la escena se reinicia.
Al entrar en la estación de regeneración, la salud comienza a aumentar hasta llegar al valor máximo.
Conclusión
El objetivo de este artículo y video correspondiente es estudiar una aplicación del método OnTriggerStay, para entender cómo funciona y posteriormente poder aplicarlo a cualquier situación en la que pueda ser útil.
Existen muchas situaciones en las que este método podría servir, por ejemplo modelar el comportamiento de una placa de presión, hacer que nos afecte una fuerza opuesta a la gravedad que nos haga levitar si estamos en determinada región. En definitiva este método es una herramienta útil que tenemos que entender.
No es el punto de este artículo estudiar el sistema de salud, pero es interesante observar que las estaciones van a actuar sobre cualquier GameObject que cuente con el script HealthSimple, independientemente de que se trate del jugador. Esto nos sugiere que en nuestro juego podríamos tener un solo script que administre la salud de cualquier ser viviente de nuestro juego y tenga propiedades comunes para todos, así como propiedades únicas para cada ser. Crear este tipo de soluciones es lo que me resulta más interesante
Introducción
En este artículo vamos a estudiar cómo crear y destruir GameObjects en tiempo de ejecución. Lograr esto es muy importante para crear juegos, porque nos permite colocar objetos cuando y donde queramos y poder posteriormente destruirlos.
En este desafío vamos a usar la estación Creation/Destruction que se ve en la figura 1, para hacer que una pequeño humanoide aparezca y desaparezca de manera cíclica mientras el juego se desarrolle.
En las figuras 2 y 3 se ilustra el ciclo de aparición y desaparición del personaje.
Las figuras 1 y 2 muestras los campos y componente en el inspector del Script «CreationDestruction».
El desafío consiste en completar los métodos createObject() y destroyObject() del Script.
Resolución
Creación del objeto
Para la creación del objeto vamos a utilizar el método Instantiate, este método está definido en la clase MonoBehaviour que por defecto es la super clase o clase padre de todo nuevo Script que hacemos en Unity.
En este momento no tengo suficientes artículos ni videos sobre programación orientada a objetos para aclarar lo de las super clases, sé que eventualmente los haré, pero por ahora si quieres saber más investiga el tema Herencia en programación orientada a objetos.
El método Instantiate tiene más de diez variantes, pero en todas básicamente necesitamos dos cosas: el objeto que vamos a crear y en qué punto del espacio lo vamos a poner.
En este caso el objeto que vamos a crear lo indicamos utilizando el prefab SmallLucy que se encuentra en la carpeta Internal Use, este prefab lo colocamos en el espacio Object To Create en el inspector, como se observa en la figura 5.
Para indicar el punto del espacio donde vamos a colocar el objeto nuevo vamos a usar un GameObject llamado Position que está en la jerarquía. También lo asignamos en el inspector (figura 5).
Vamos a utilizar una variante del método Instantiate que creará el objeto y lo colocará en la jerarquía como hijo del GameObject que le indiquemos. Esto quiere decir que nuestro objeto aparecerá en la posición del GameObject padre (Position) más el desplazamiento propio que SmallLucy tenga (en este caso SmallLucy se encuentra en el origen así que su desplazamiento es cero).
Sé que el párrafo de arriba está algo confuso, más adelante me gustaría hacer un video y artículo sobre coordenadas globales y locales para poder explicar esto con más claridad. Por ahora sigamos adelante. Escribimos la siguiente línea en el método createObject:
Vamos por parte, en primer lugar createdObject es un objeto de tipo GameObject auxiliar (ver figura 4) que definimos para guardar la referencia del objeto nuevo que vamos a crear. Esto es muy importante porque sino más adelante no sabremos cuál objeto tenemos que destruir.
El método Instantiate va a devolver un objeto tipo GameObject (el objeto nuevo) y con el signo igual lo asignamos a createdObject.
Entre paréntesis indicamos los dos parámetros separamos por una coma. El primer parámetro es el objeto a crear y el segundo es la componente Transform del GameObject Position
Destrucción del objeto
Para destruir al objeto usamos el método Destroy (que está definido en la clase MonoBehaviour) y le damos como parámetro la referencia del objeto que hemos guardado en el campo createdObject. Esto lo escribimos en el método destroyObject.
Comportamiento cíclico
Queremos que Lucy aparezca y desaparezca continuamente en la estación Creation Destruction, así que tenemos que hacer que ejecutar el método createObject. Luego esperar unos segundos y llamar al método destroyObject, luego esperar y volver a llamar al método crear.
Esto lo logramos primero llamando al método createObject desde Start, de esa forma al iniciar el juego, Lucy aparece. Luego al final del método crear usamos Invoke para llamar al método destroyObject luego de dos segundos. Hacemos lo mismo al final del método destroyObject, usamos Invoke para llamar al método crear. Esto lo podemos ver en la figura 6.
Conclusión
Hemos conseguido hacer aparecer nuevos objetos en el escenario en tiempo de ejecución, es decir mientras el juego está corriendo, esto no es poca cosa, entendiendo esto podemos lograr muchas cosas.
Para crear un nuevo objeto en el mundo básicamente necesitamos una copia del objeto a crear, esto lo logramos con un prefab. Y tenemos que saber exactamente dónde colocarlo, esto se puede lograr de muchas formas, por eso el método Instantiate tiene tantas variantes.
Si queremos destruir un GameObject de la jerarquía necesitamos saber cuál es, por eso es muy importante la referencia del objeto, si creamos el objeto sin asignarlo a ningún campo, el objeto estará en la jerarquía pero no podremos hacer nada con él a menos que lo encontremos nuevamente.
Introducción
En este artículo vamos a analizar cómo aplicar en Unity el método LookAt, para hacer que un GameObject mire en la dirección de otro. Esto se traduce en la orientación de uno de los ejes del GameObject de modo que apunte hacie el origen del GameObject objetivo.
Vamos a trabajar con la estación Look At, la cual consiste en una cápsula de contención en la que se encuentra flotando el modelo de Lucy. El objetivo es lograr que Lucy nos siga con la mirada por todo el escenario.
En la jerarquía tenemos un GameObject llamado «#3 LookAtObject».
Este GameObject tiene asignado el Script «LookAtObject», que se encargará de hacer que Lucy siga con su mirada al jugador.
En la figura 4 se observa que hay 3 campos para completar, el primero es para el objeto observador, el segundo para el objetivo de observación y el tercero es para que Lucy mire a una altura fija del escenario, de esta forma no se sale de la frontera de su cápsula de contención.
Vamos a asignar a Lucy directamente desde la jerarquía y al personaje lo vamos a encontrar a través de su tag.
Si querés aprender distintas formas de encontrar las referencias de los GameObjects de la jerarquía para usar en los Scripts podés leer el artículo anterior o mirar este video.
Si abrimos el Script encontramos algunas cosas hechas. En el método FixedUpdate, que se ejecuta una vez cada cierto tiempo, hacemos la llamada al método «lookAtObject», que se encargará de cumplir la función.
En el método start que se ve en la figura 5, tenemos una instrucción que estaba comentada al momento de hacer la captura. Hay que quitar las barras de comentarios para encontrar la referencia del jugador y lograr que Lucy lo mire.
En la figura 6 se observan los campos definidos en el Script. Vamos a utilizar el Vector3 llamado «objectToLookPosition» para las coordenadas a la que Lucy debe mirar.
Dentro del método «lookAtObject» escribimos estas instrucciones:
Con estas dos instrucciones logramos que Lucy esté orientada todo el tiempo hacia el origen del jugador.
El desafío está parcialmente resuelto, aún tenemos que solucionar el problema que se ilustra en la figura 9.
Primero entendamos qué está pasando.
Todos los GameObjects tienen una coordenada en el espacio donde se encuentra su origen.
El método lookAt va a modificar la orientación del objeto al que se lo aplique (en este caso Lucy). Lo hará de tal forma que el eje local forward apunte hacia el origen del objeto a mirar. Como se ilustra en la siguiente figura.
Si el personaje está lejos de Lucy su inclinación es pequeña, pero al acercarse pasa lo siguiente:
¿Cómo podemos corregir esto?
Tenemos que hacer que Lucy mire hacia una coordenada que esté a la misma altura que su origen. De esa forma su ángulo de inclinación será pequeño.
Ásí que vamos a sobreescribir la componente y del Vector3 por el valor de la variable «yPos» que ajustaremos desde el inspector.
Idealmente podríamos hacer que la componente y del Vector3 valga exactamente la altaltura del origen de Lucy, esto es algo que me di cuenta luego en la post producción del video. Sin embargo está bueno como ejemplo de que no hay una sola forma de resolver los problemas.
Se puede probar escribir la variable yPos en tiempo de ejecución, pero al parar la simulación todos los valores volverán a su valor inicial.
El valor 0.75 funciona bien para este caso. Un número menor a este hace que Lucy se incline hacia abajo y salga por el frente de la cápsula.
En el siguiente artículo estudiaremos cómo crear y destruir objetos en tiempo de ejecución. Suscríbete al canal de YouTube para estar al tanto de los nuevos videos y artículos.
En este artículo vamos a estudiar distintas formas de encontrar, desde un Script, los GameObjects (objetos) que se encuentran en la jerarquía. Entre las formas tenemos asignar directamente los objetos desde el inspector o encontrarlos a través de métodos como «FindGameObject».
Antes de empezar te invito a ver el siguiente video en el que se resuelve este problema:
🟢 INTRODUCCIÓN a la serie sobre encontrar las referencias de los GameObjects y componentes de la escena en Unity
Procedimiento
Vamos a trabajar con la estación Find GameObjects, que consiste en 5 objetos sobre una mesa. La función de esta estación es regresar al estado de reposo a los objetos que son perturbados.
El problema es que inicialmente no tenemos las referencias de los objetos, así que la función no se puede llevar a cabo.
Dentro del Script «FindGameObject» tenemos algo de código ya escrito.
Los 5 objetos están declarados como privados y están serializados, por eso aparecen en el inspector (como se observa en la siguiente figura).
En el método Start se hace la llamada a 5 métodos que se encargarán de encontrar las referencias.
Los métodos se encuentran incompletos. Nuestro objetivo es completarlos y descubrir distintas formas de encontrar las referencias.
Forma #1: Asignar los objetos directamente en el inspector a un campo serializado.
Como se observa en la figura 4, todos los objetos están definidos como privados y están serializados, pero esto es más que nada para que veamos en el inspector, cómo al iniciar el juego encontramos la referencia.
Para la forma 1, tomamos el objeto de la jerarquía y lo arrastramos al campo en el inspector. Como se ilustra a continuación.
Con esto ya le decimos a nuestro Script qué objeto de la jerarquía es el GameObject definido con el nombre «Object1a».
Forma #2: Asignar los objetos directamente en el inspector a un campo público.
Esta forma es prácticamente igual que la anterior, sólo que ahora el GameObject lo definimos como público.
Definir un campo como público hace que sea accesible desde cualquier contexto y por lo tanto también aparece en el inspector.
Como en la forma anterior, tomamos el GameObject de la jerarquía y lo arrastramos al campo en el inspector.
Forma #3: Etiquetas. Método FindGameObjectWithTag de la clase GameObject.
La clase GameObject cuenta con un método que permite encontrar un GameObject en la jerarquía utilizando las etiquetas.
Luego procedemos a escribir el código necesario para encontrar el GameObject desde el Script. Vamos a escribirlo dentro del método «findGameObject2» que se ve en la figura 7.
Vamos a analizarla por partes, al escribir «object2=» estamos diciendo que el campo object2 va a valer lo que sea que coloquemos luego del signo «=». Como se observa en la figura 9, object2 es de tipo GameObject, por lo tanto lo que coloquemos luego del signo «=» tendrá que devolver un objeto de tipo GameObject.
Al escribir «GameObject.» (GameObject punto), estamos indicando que queremos acceder a los atributos y métodos que están definidos en la clase GameObject.
Ejecutamos un método que se llama FindGameObjectWithTag» (traducido significa: «encontrar GameObject con etiqueta»), este método necesita que le ingresemos (dentro de los paréntesis) el String con la etiqueta.
Leer esto e interpretarlo es algo complicado, pero de a poco va cobrando sentido conforme vamos aprendiendo.
En el video observamos que al ejecutar el juego, logramos encontrar la referencia de object2.
En el lenguaje C# se distinguen mayúsculas y minúsculas, por lo tanto hay que respetarlas.
Forma #4: Nombre. Método Find de la clase GameObject.
Como se observa en la figura 10 arriba del menú desplegable Tag, hay un espacio con el texto «Object2», esto es el nombre que tiene asignado el GameObject y con ese nombre aparece listado en la jerarquía.
Utilizando el método Find de la clase GameObject podemos encontrar un GameObject por su nombre, de la siguiente forma:
object3=GameObject.Find(«Object3»);
Con esta instrucción, Unity revisará la jerarquía, encontrará el objeto llamado «Object3» (si es que hay uno) y lo asignará al campo object3.
Si no hay ningún GameObject llamado «Object3» en la jerarquía, el campo object3 tendrá el valor null. Si hay más de un objeto que tiene el mismo nombre, no podemos estar seguros de que vamos a encontrar el que queremos.
Forma #5: Componente única. Método FindObjectOfType<T>.
La última forma que vamos a ver es un poco más complicada.
La clase GameObject nos permite encontrar la referencia a una componente que esté presente en la jerarquía, por ejemplo la componente Transform, Collider, RigidBody, etc.
Por supuesto, prácticamente todos los GameObjects tienen la componente Transform, entonces en principio no sería muy útil. Pero ¿Qué pasaría si la componente que nos interesa es única en la jerarquía? Es decir, sabemos que hay un solo GameObject en la jerarquía que la tiene. Esto podría servirnos, porque encontrar esa componente única es equivalente a encontrar ese GameObject.
Podría ser cualquier componente siempre que sea única, en este caso creamos un nuevo Script con el nombre: «Object4Script» y se la asignamos al GameObject de la jerarquía llamado «Object4».
Luego escribimos el siguiente código en el método «findGameObject4» (ver figura 7).
Primero encontramos la referencia del objeto tipo Object4Script con el método FindObjectOfType<T> de la clase GameObject, luego accedemos a su componente transform por medio del operador punto y luego a la componente gameObject. El resultado de esto lo asignamos a object4.
De esta forma logramos encontrar el GameObject a partir de una de sus componentes. Por supuesto, si hay otro GameObject que también tiene ese componente, podríamos encontrar el GameObject equivocado.
Introducción
En este artículo vamos a leer entradas del teclado y el mouse en Unity utilizando la clase Input de Unity. Esta clase también nos permite acceder a otros periféricos como joysticks, entradas táctiles, acelerómetro, giróscopo, entre otras señales de entrada.
En el primer video vamos a trabajar en la estación de entradas, que consiste en modelos para las teclas «WASD» y botones del mouse.
El objetivo es lograr que cambien de color cuando la entrada correspondiente esté pulsada.
En la jerarquía hay un GameObject llamado #1 Input. Este objeto tiene todos los elementos relacionados a la estación de entradas.
Este GameObject tiene asignado el script Read Input, que será el encargado de leer las entradas y realizar las acciones sobre los elementos de la estación.
No es necesario hacer nada en la jerarquía. Vamos a la carpeta «Scripts to Complete», «Video 1 – Read Inputs» y abrimos el script «ReadInput».
¿Por qué el código debe ir en el método Update?
Todos los Scripts que extienden su comportamiento de la clase MonoBehaviour tienen implícito el método Update, el cual se evalúa automáticamente en cada frame de nuestro juego.
Como se explica en el video, si nuestro juego funciona a 60 fps constantes, el método Update se ejecuta 60 veces por segundo.
La lectura de las entradas es un evento aleatorio, por lo tanto no podemos determinar en qué momento el jugador presionará un botón. Por esta razón, cuando necesitamos leer las entradas, debemos hacerlo en todos los frames.
¿Cómo hacemos la lectura de las entradas?
Imaginemos que podemos preguntar a la computadora en lenguaje coloquial por el estado de las entradas, ¿Qué preguntas le haríamos?
Preguntas simples como las siguientes.
Si la respuesta a estas preguntas es si, ejecutaremos una acción apropiada para cada una.
Ya tenemos la idea, ahora solo tenemos que hacer estas preguntas utilizando un lenguaje que la computadora entienda.
Utilizando la sentencia if, podemos hacer preguntas cuya respuesta es verdadero o falso.
La clase Input de Unity se encarga de manejar las entradas, así que recurrimos a sus métodos para resolver el problema. Tenemos el método GetKey para las teclas y GetMouseButton para los botones del mouse, en el argumento de estos métodos indicamos la tecla utilizando el enum KeyCode y el botón del mouse usando enteros, como se observa en la figura 6.
Solución
Con esto logramos que la estación de entradas cumpla su función.
Conclusión
Como primera conclusión me gustaría mencionar cómo pasamos de pensar el problema en lenguaje coloquial (figura 5), para luego escribirlo en lenguaje C# (figura 6). Pensar los problemas de esta forma resulta más simple, porque nos abstraemos del lenguaje de programación. Un paso intermedio entre este lenguaje coloquial y el código C# sería el pseudocódigo.
Leer entradas es la forma que tenemos de saber qué quiere hacer el jugador, así que tenemos que definir qué entradas vamos a ofrecer y cuándo queremos leerlas (por ejemplo quizás no nos interesa leer las entradas WASD cuando mostramos una cinemática).
Los eventos de entrada son sucesos aleatorios, es por eso que debemos leerlos de manera continua utilizando el método Update.
Para evitar complicaciones es recomendable hacer la lectura de las entradas en un solo Script.
Puede haber otro tipo de entradas, como un JoyStick o entrada táctil. Debemos estudiar la clase Input de Unity para entender cómo manejarlas.
Introducción – ¿Qué es un método en programación?
ACLARACIÓN IMPORTANTE ANTES DE EMPEZAR En programación, cuando vean la palabra «MÉTODO» normalmente se trata de un CONJUNTO DE INSTRUCCIONES DE CÓDIGO agrupadas dentro de una función. Recuerdo que este término me resultaba un poco extraño y solo cuando estudié programación orientada a objetos entendí la interpretación de la palabra «Método» en este contexto.
En este artículo vemos qué son los métodos en programación y encontrarás un vídeo de mi canal de YouTube en el que está resumida esta informacion.
Los métodos de programación sirven para agrupar instrucciones de código y luego este conjunto de instrucciones pueden ser llamadas cuantas veces sean necesarias simplemente haciendo la «llamada al método«, esto nos permite reutilizar código y resolver problemas cada vez mas complejos gracias al aumento de abstracción sobre un problema.
En este artículo se incluye como ejemplos la declaración de cuatro métodos de programación, un método void sin parámetros de entrada, otro método void con parámetros de entrada, un método con parámetro de salida pero sin parámetros de entrada y por último un método con parámetros de entrada y de salida.
En programación, método se le llama a un bloque de código que tiene definido en su interior un conjunto de instrucciones, estas instrucciones realizan una determinada tarea. Cuando se necesita hacer uso de la función definida en el método simplemente se lo llama por su nombre, cuando el flujo del programa pasa por una llamada a un método el puntero salta a la región donde está definido el método, ejecuta todas sus instrucciones y al finalizar retorna a la línea posterior a la llamada al método.
Para definir un método hay que indicar si tendrá o no parámetros de salida, es decir si el método produce un dato como resultado de su ejecución y en caso afirmativo indicar ese tipo de dato. Luego se debe definir un nombre de identificación, por convención debe comenzar con la primera letra en mayúscula, además de intentar que el nombre sea representativo de la función que desempeña. Luego debemos indicar si tiene o no parámetros de entrada, en caso afirmativo, para cada parámetro de entrada incluir el tipo de cada uno y el nombre con el que se conocerá dicho parámetro dentro del método. Finalmente dentro del método se insertan todas las instrucciones de código a ejecutar, estas instrucciones pueden incluir la llamada a otros métodos, incluso un método puede llamarse a si mismo dando lugar a algoritmos recursivos, en este último caso, de no establecer bien la condición de finalización de las llamadas recursivas al método, tendríamos un método que se llama indefinidamente hasta que la pila de ejecuciones colapsa dando lugar al famoso error «Stack Overflow».
Módularización
En la figura 1 vemos al método representado como una caja, en la que aparece el nombre del método como título, se especifica el inicio y el final del método y el conjunto de instrucciones se encuentra dentro de esta región.
Para entender de qué se trata la modularización vamos a ver la figura 2. En la izquierda vemos representada una lista larga de instrucciones de programación.
Ahora dentro de esa lista hay cierto número de instrucciones que se utilizan en más de un lugar, las instrucciones A, B, C y D. Digamos que estas instrucciones realizan una tarea en concreto y siempre se ejecutan juntas.
Supongamos que ahora debemos hacer cambios en esas instrucciones (por ejemplo para mejorar la manera en la que resuelve la tarea o agregar funcionalidad), lo que ocurre es que debemos identificar todas las regiones donde están esas instrucciones.
Seria genial si pudiésemos cambiar las cosas en un solo lugar y los cambios se apliquen en todas las regiones donde se usen estas instrucciones, ¿no?
Esto es precisamente lo que logramos con los métodos, nos permiten agrupar conjuntos de instrucciones en un módulo independiente, una caja negra por así decirlo, aquí es donde entra en juego el concepto de abstracción, sabemos que el método cumple una determinada función pero desde afuera no nos interesa realmente lo que hay en su interior, el método puede ser llamado cuando sea necesario sabiendo que cumplirá la función que le fue programada previamente. Como se observa a la derecha en la figura 2, las instrucciones ahora fueron reemplazadas por el nombre del método.
Parámetros de entrada y salida
En la figura 1 hay flechas que entran y salen del método. Con esto intento representar la entrada y salida de parámetros.
Podemos hacer que nuestro méteodo requiera parámetros de entrada, los cuales usamos en el interior para hacer cálculos o realizar cualquier tipo de tarea.
Además podemos hacer que la ejecución del método produzca un dato de salida, que usaremos fuera del método.
Métodos públicos y privados – Visibilidad
Por último en la figura 1 vemos un ojo normal y otro ojo tachado. Esto representa la visibilidad que tendrá el método, lo cual es un tema de programación orientada a objetos, no vamos a profundizar en este artículo pero en principio digamos que podemos tener métodos públicos y métodos privados.
Los métodos públicos podremos ejecutarlos desde otros Scripts por ejemplo, o podremos ejecutarlos desde un componente en la jerarquía en Unity, por ejemplo un botón.
Los métodos privados no serán accesibles desde contextos externos al Script donde está definido.
Sintaxis
La sintaxis es el conjunto de reglas establecidas en un lenguaje para escribir el código, en la figura 3 vemos posibles sintaxis de un método,
Esta sintaxis se puede aplicar al lenguaje C# y Java, un detalle es que todos los métodos son públicos, pero podríamos reemplazar la palabra «public» por «private» y la sintaxis sería correcta.
Declaración de un método
Ejemplo 1 – Método void que no requiere parámetros
Analicemos el método que se encuentra arriba a la izquierda en la figura 3. Tenemos la estructura de un método público que no requiere parámetros y no devuelve parámetros.
Observamos que ha sido declarado como privado en lugar de público, seguidamente encontramos la palabra «void» con la que indicamos que este método no va a devolver parámetros. Luego el nombre del método: «placePlayerRandomly». Se abre y se cierran paréntesis con lo que se indica que este método no necesita que le demos parámetros.
El comienzo y final del método se indica utilizando llaves. En el interior estarán todas las instrucciones del método.
Invocación o llamada a un método
Una vez que el método está definido podemos hacer que se ejecute desde cualquier parte del script, incluso podemos invocarlo desde otros scripts.
En la siguiente figura se muestra la invocación al método «placePlayerRandomly» efectuada en el método «startGame» del mismo script «GameControl».
Para invocar este método se escribe su nombre y se abren y cierran paréntesis, cerramos la instrucción con punto y coma. Haciendo esto estamos logrando que se ejecuten todas las instrucciones del método.
Noten como los nombres de los métodos ya nos van ayudando a entender lo que está pasando. Al comenzar el juego se debe colocar el personaje aleatoriamente.
Desde el punto de vista de «startGame» el método «placePlayerRandomly» es una función que hace todo lo necesario para colocar el personaje aleatoriamente. El método «startGame» no sabe cómo es que lo hace exactamente pero no le importa, debido a que «placePlayerRandomly» hace bien su trabajo.
Ejemplo 2 – Método void con parámetros de entrada
En la esquina superior derecha de la figura 3 tenemos la estructura de un método que no devuelve parámetros pero si los requiere para funcionar.
Este método requiere dos parámetros para funcionar: un valor entero m que indicará los minutos del timer y un valor entero s que indicará los segundos.
La invocación de este método ocurre en varios lugares del código, en particular el método «addSeconds» perteneciente al Script «Timer», este método recibe como parámetros un entero «s» que representa la cantidad de segundos que se deben agregar al timer debido a que el personaje agarró uno de los relojes que hay en el escenario. El método «addSeconds» hace algunas operaciones con la variable «s» para actualizar el tiempo y finalmente ejecuta el método «writeTimer» que muestra los nuevos valores de tiempo en pantalla.
Dos observaciones: la primera es que como estamos ejecutando el método desde otro Script es necesario agregar «uiManager.» (prestar atención al punto) antes de escribir el nombre del método «writeTimer». La segunda es que los parámetros se ingresan dentro de los paréntesis y separados por coma.
En ambos scripts utilicé nombres confusos (m y s) a propósito para que en el futuro, cuando hablemos sobre contextos, nos sirva para analizar.
Ejemplo 3 – Método con parámetro de salida pero no de entrada
Pasamos a los métodos que devuelven parámetros.
El siguiente ejemplo que se corresponde con la estructura ilustrada en la esquina inferior izquierda de la figura 3, un método que devuelve un dato y no requiere parámetros para funcionar.
El dato que devuelve este método es un «Vector3» y se indica en la declaración, luego de la palabra «public». Observen que la primer línea que no es un comentario dice: «Vector3 position;», ahí estamos declarando un Vector3 que llamamos «position», luego hacemos algunos cálculos y al final del método escribimos: «return position;» indicando que devolvemos ese Vector3.
Este método lo que hace es devolver un Vector3 (componente x,y,z) que representa una posición aleatoria que pertenece al interior de una determinada pieza de laberinto. De esta forma podemos usar esa posición para colocar el pedestal o los relojes sin preocuparnos por ejemplo de que aparezcan incrustados en una pared.
No es fácil entender la instrucción resaltada en la figura 9. Por ahora observemos dos cosas, la primera es que hacemos una llamada al método «getRandomPosition» utilizando su nombre (como se ve al final de la instrucción). La segunda es que el resultado de esa invocación es un dato Vector3, por lo tanto, utilizando el signo igual, lo asignamos al dato «rP» que se define como Vector3.
Ejemplo 4 – Métodos con parámetros de entrada y salida
El último ejemplo se corresponde con la estructura ilustrada en la esquina inferior derecha de la figura 3, un método que devuelve un dato y requiere parámetros para funcionar.
Vemos que en la declaración decimos que el método «isBestScore» devuelve un dato tipo bool y requiere un dato tipo int que llamamos «val».
El método «isBestScore» devuelve una variable que puede valer verdadero o false (true or false). La utilidad de este método es que lo utilizamos para preguntar si la puntuación obtenida en la partida (val) es mejor que la que hay guardada hasta el momento (bestScoreValue).
La invocación a este método se hace en el método «gameWon». Como el método devuelve un valor tipo bool, lo podemos usar directamente como argumento de una sentencia if, debido a que «score.isBestScore(time)» es equivalente a tener un valor verdadero o falso.
Método StartGame del Script GameControl
Para terminar la figura 12 se observa el método «startGame» junto con los demás métodos a los que va invocando.
Además de agrupar instrucciones, un método debe tener un propósito bien establecido y que sea coherente con el nombre que le dimos, de esta forma podremos saber rápidamente cúal es su funcion y qué tipo de instrucciones puede contener.
Por ejemplo el método «startGame» se encarga de coordinar una serie de acciones para comenzar el juego, pero no es él quien directamente realiza estas acciones, sino que invoca a otros métodos con tareas más específicas.
De esta forma nos resulta más simple realizar modificaciones en el código y depurar errores.
Conclusión
Los métodos constituyen una poderosa herramienta a la hora de elaborar soluciones específicas, eficientes, reutilizables y sostenibles en el tiempo.
Sostenibles en el tiempo porque en todas las etapas del desarrollo deberemos hacer cambios, de modo que tenemos que ser capaces de recordar o comprender rápidamente cómo funciona nuestro código.
Esto se logra utilizando nombres descriptivos, documentando nuestro código y aplicando el paradigma de orientación a objetos.
En este artículo vamos a explicar qué es una variable en programación, qué tipos de variables existen, para qué se usan y mostrar algunos ejemplos en lenguaje C# en el desarrollo de videojuegos en Unity.
El concepto de variable se utiliza en muchas disciplinas, el ejemplo más común quizás es la variable x en una función matemática, en este caso particular la palabra «variable» hace referencia a un elemento que puede tomar distintos valores, normalmente se suele tomar a X como la variable independiente y por lo tanto en una función matemática a cada valor de X distinto le corresponderá un valor de la variable dependiente Y. Pero en programación la palabra «variable» hace referencia a un concepto un poco distinto.
Para entender qué es una variable en programación vamos a ver un poco sobre memorias de computadoras.
Las memorias almacenan información en forma de registros de bits (es decir conjuntos de valores que pueden ser 0 o 1). Esta información será interpretada y utilizada por el procesador al correr nuestros programas. Las memorias a su vez cuentan con muchos de estos registros, así que cada registro tiene una dirección que permite encontrarlo, leerlo y escribirlo.
Entonces podemos decir que una variable es un DATO que se aloja en la memoria de la computadora. El nombre de identificación que le asignamos está asociado a la dirección dentro de la memoria y el valor que guardamos es la información que contiene la variable.
Ejemplos de variables según su tipo
En programación existen distintos tipos de variables, se utilizará un tipo de variable apropiada según la información que necesitemos almacenar. Tomemos en cuenta la siguiente tabla de información.
La variable «edad» contiene el valor 22, esto quiere decir que cuando nosotros usemos la palabra «edad» en nuestro programa, indirectamente estaremos usando el valor 22. Hay que tener en cuenta de que el valor de una variable se puede modificar durante la ejecución de un programa.
Si hacemos la operación «2*edad» (2 multiplicado por edad), esa instrucción tendrá un resultado igual a 44.
Elección de nombres para las variables
En la figura 2 se muestran variables que han sido definidas con nombres confusos. Esto suele pasar muy a menudo cuando queremos resolver los problemas rápidamente. Es importante elegir nombres representativos, porque luego de un tiempo olvidamos lo que hicimos y si necesitamos hacer cambios resultará difícil entender el código.
La variable «casa» de la figura 2, tiene el valor «falso». Esta variable la pudimos haber utilizado, por ejemplo, para saber si un personaje está en su casa y si es verdadera restaurar su salud.
Cuando le damos un contexto, le encontramos sentido al nombre «casa» para identificar una variable de verdadero o falso, esto significa que el personaje no está en su casa. Sin embargo nos puede tomar un buen rato descifrar cuál era la función de la variable.
Podemos ahorrarnos el esfuerzo simplemente definiendo la variable como «personajeEnCasa». Ahora el nombre de la variable es representativo de la función que cumple!
Tipos de Variables en Programación
Conozcamos las variables más básicas que vamos a usar para resolver nuestros problemas. Los ejemplos fueron tomados de la serie del laberinto.
Variables tipo Boolean (bool)
Las variables tipo «bool» reciben su nombre del Álgebra de Boole desarrollada por el matemático George Boole. Pueden encontrarse en 2 estados posibles: True o False (verdadero o falso). Las utilizamos para resolver operaciones lógicas.
En el método que se ve en la figura 3, definimos el bool «validSelection» y lo inicializamos con el valor falso.
Dentro del bucle while se selecciona una pieza al azar del laberinto y se verifica si está lo suficientemente lejos del personaje.
Si la pieza de laberinto está muy cerca del personaje, validSelection sigue siendo false y el programa vuelve a elegir otra pieza de laberinto.
Si la pieza de laberinto está lo suficientemente lejos, validSelection se hará verdadera y el programa seguirá adelante utilizando esa pieza.
Variables tipo Integer (int)
Las variables tipo «int» sirven para almacenar valores enteros positivos y negativos.
En el método que se ve en la figura 4 se ven varios números enteros, «nPieces», «labyrinthPieces.Length», «nClocks», los números 0 y 1 y la variable de iteración «i».
Tomemos el caso de la variable iteradora «i», está declarada e inicializada con valor 0 dentro del bucle for y sirve para ejecutar el método «placeAClock» (colocar un reloj), las instrucciones dentro del bucle se repetirán «nClocks» veces, siendo nClocks una variable entera que indica cuántos relojes deben haber en el escenario.
Por ejemplo si queremos que haya 10 relojes en el escenario, hacemos que «nClocks» valga 10, entonces el bucle for ejecutará 10 veces el método «placeAClock».
Para la ocasión de Halloween definimos un Script para controlar el NPC Lucy, un espectro que mora en el laberinto. Lucy persigue al personaje con una determinada velocidad.
Para resolver este comportamiento hacemos una interpolación lineal entre la posición del personaje y la posición de Lucy utilizando como parámetro el float «velocity» multiplicado por el float «Time.deltaTime».
El método «showMessage» que se ve en la figura 9 pertenece al script «UIManager», este método recibe como parámetro un string llamado «message» y se encarga de mostrarlo en la interfaz de usuario, tal como se ilustra en la figura 10.
Conclusión
En este artículo vimos qué es una variable en programación y cómo podemos usarla para representar distintos tipos de datos.
Una variable en programación es una referencia a un espacio en la memoria en el que está almacenado un dato. Podemos asignarle el nombre que queramos y al utilizar ese nombre estaremos haciendo referencia a ese dato almacenado en esa determinada parte de la memoria.
Vídeos sobre VARIABLES en programación
Qué son y para qué sirven las variables en programación
Cómo leer variables que están definidas en otro Script en Unity
En el canal tengo un vídeo que habla sobre cómo acceder desde un Script a una variable que está definida en otro Script y así poder leer su estado o modificarla si se necesita.
Información actualizada sobre esta entrada
Este artículo pertenece a una serie que consiste en hacer un juego simple en primera persona acerca de encontrar objetos dentro de un laberinto. Es una de mis primeras series de cuando empecé el canal, ahora he mejorado mucho este proyecto y puedes descargar el código fuente para importarlo en tu propio proyecto de Unity. Algún día vamos a hacer un remake de esta serie, suscríbete a mi canal para estar al tanto del nuevo contenido sobre Blender, Unity y programación.
Sígueme en itch.io y descarga el código fuente de este proyecto
PUEDES TESTEAR ESTE JUEGO AQUÍ. TAL VEZ TARDE UN POCO EN CARGAR 🔻
MOVEMENT: WASD CAMERA LOOK: MOUSE
Introducción al artículo original
En este artículo vamos a importar assets, es decir modelos 3D y texturas, agregarlos al motor Unity y configurarlos para que estén preparados para empezar a trabajar en el escenario. Vamos a crear GameObjects prefabricados que luego podremos reutilizar y vamos a modificar el cielo que viene por defecto, reemplazándolo por un Skybox donde aplicaremos las texturas que se descargaron de Asset Store en el video anterior.
Lo primero que vamos a hacer es descargar los archivos necesarios para el proyecto. Pueden hacerlo en el siguiente link.
Modelos 3D y Texturas
Dentro de estos archivos encontraremos modelos 3D para los muros del laberinto, un pedestal, una espada y un reloj. Cada modelo tiene sus propias texturas.
Seleccionamos las carpetas y las arrastramos a la carpeta apropiada en Unity.
Esto lo hago primero seleccionando los archivos, luego haciendo clic para arrastrarlos (aparece un ícono fantasma indicando la cantidad de archivos que se está arrastrando) y luego aprentando la combinación ALT-TAB para cambiar de ventana, esto no hace que se pierda la selección, es por eso que podemos soltar los archivos en la carpeta de Unity.
Si hay problemas para hacer esto se puede minimizar la ventana de Unity o utilizar las opciones de importación de Unity.
Luego hacemos lo mismo con los modelos 3D. Hay que tener en cuenta las carpetas que creamos en el video anterior para poder organizarnos.
Modificar escenario
Ahora vamos a colocar todas los modelos 3D en el escenario para comenzar a darle forma al laberinto.
Primero eliminamos todos los elementos del escenario excepto el suelo. En el video anterior los habíamos colocados todos como hijos de un Empty GameObject llamado Escenario.
El siguiente paso es tomar el modelo 3D llamado ElementosEscenario que importamos y arrastrarlo hacia la escena o la jerarquía. Esto colocará todas las piezas del laberinto en el escenario.
En el video anterior habíamos hecho que el suelo tenga un color marrón. Ahora vamos a aplicarle texturas así que hacemos que vuelva a ser de color blanco, de lo contrario nuestra textura tendrá un tinte marrón.
Aplicar texturas al suelo
Ahora vamos a utilizar las texturas que vienen dentro del zip que se puede descargar al inicio del artículo.
Comenzamos con el suelo, dentro de la carpeta tenemos tres texturas.
La textura Base Color se utiliza para darle color al material. Metallic determina el comportamiento que tiene el material frente a la luz y la textura normal también determina cómo son los rebotes de luz en el material, pero se utiliza para agregar detalles geométricos que aparentan una alta densidad de polígonos en los modelos 3D.
Colocar texturas en los slots del material
Las texturas las agregamos en el inspector, para poder ver el material en el inspector tenemos dos opciones: podemos seleccionar el material directamente desde la carpeta del proyecto o seleccionando un modelo 3D del mundo que la tenga asignada.
En la figura 8 se observa que las texturas están asignadas en los slots del material.
El Slot Albedo determina el color del material, ahí colocamos la textura Base Color. La textura metallic en el slot metallic y la textura normal en el slot Normal map. Para esto último deberemos definir esa textura como un mapa de normales, hay dos formas de hacer esto, pero Unity nos da la opción en ese mismo lugar, como se observa en la figura 8 aparece un cartel que dice que esa textura no está definida como un mapa de normales y nos aparece un botón para arreglarlo. Hacemos clic en Fix Now.
Tiling de las texturas
En la esquina superior izquierda de la figura 8 se ve una porción del suelo. Noten que el suelo se ve borroso a diferencia de cómo debería ser (un suelo de cesped con margaritas).
Esto ocurre porque la textura está expandida hasta ocupar todo el plano, para cambiar esto debemos hacer que se repita más veces en la geometría. Esto se hace con el parámetro Tiling del material, en mi caso (por el tamaño del plano) los valores 100 para X y 100 para Y funcionan.
Lo que va a ocurrir es que la misma textura se haga más pequeña y se coloque una a continuación de la otra. En la figura 10 se observa el cesped con margaritas. Noten como en la parte inferior de la imagen el suelo se ve bien, pero a medida que nos alejamos se vuelve más evidente el patrón de la textura, resulta obvio que es una misma textura que se repite.
Estamos usando una textura «Seamless» (sin costura), es decir una textura que al ponerla una a continuación de la otra (en los cuatro lados) encajan perfectamente y no se nota una línea de ruptura. Por más que la textura sea muy buena no podremos evitar que a la distancia se evidencie el patrón de repetición. Para evitar esto hay que usar más texturas, colocar objetos que interrumpan el patrón y demás.
En la figura 10 también se observa que el suelo refleja bastante luz, como si estuviese hecho de cristal o algo parecido. Para corregir esto disminuimos el valor de Smoothness, haciendo que el material refleje menos luz.
Extraer materiales de los modelos 3D
En versiones anteriores, cuando importábamos un archivo con extensión FBX, los materiales que pudieran estar definidos aparecían automáticamente junto con los modelos. Esto ha cambiado y creo que tiene sentido que tengamos que extraer manualmente los materiales, de esa forma podemos llevar un mejor control y evitar tener muchas copias del mismo material.
Hay dos formas de extraer el material, al menos en la versión al momento de grabar el video.
En este caso hacemos clic sobre el modelo importado y en el inspector vamos a la pestaña materiales y hacemos clic en: «Extract from prefab».
Aparece una ventana para seleccionar la ubicación de los materiales extraídos, si se quiere podemos crear una carpeta para los nuevos materiales.
Los nuevos materiales aparecen en la carpeta seleccionada.
Aplicar texturas a los nuevos modelos 3D
El siguiente paso es hacer lo mismo que hicimos con el material del suelo, vamos a ir material por material agregando las texturas a los respectivos slots.
Hay un problema que surge cuando tenemos que hacer este tipo de tareas y es que cuando seleccionamos algo en la jerarquía o la carpeta del proyecto, el inspector nos muestra información sobre esa selección. En nuestro caso sería bueno que el inspector quede bloqueado mostrando el material que estamos configurando.
Para esto está el candadito pequeño que se ve en la esquina superior derecha de la pestaña inspector. Haciendo clic en él bloqueamos lo que muestra el inspector y podemos navegar libremente por las carpetas del proyecto sin perder de vista nuestro material. Cuidado que esto también puede ser un problema, a veces se nos olvida el inspector bloqueado y no sabemos por qué no podemos ver información sobre lo que seleccionamos.
Otra alternativa para este tipo de tareas es modificar el layout de Unity para nuestro beneficio, es decir abrir más pestañas del proyecto y bloquearlas para que cada una muestre una cosa.
En la figura 16 se observa que una de mis ventanas del proyecto muestra los materiales, la otra las texturas y el inspector muestra el material seleccionado. Esto hace que el proceso de agregar muchas texturas a los materiales sea más rápido.
Creación de GameObjects prefabricados
Una vez que hemos configurado todos los materiales, el siguiente paso es crear los «Prefabs» es decir GameObjects prefabricados que posteriormente podremos instanciar durante el diseño o en tiempo de ejecución del juego. Por ejemplo más adelante haremos que los relojes aparezcan aleatoriamente en el escenario. Para poder lograr eso necesitamos contar con un GameObject prefabricado del cual se crearán clones.
Para crear un GameObject prefabricado simplemente lo tomamos de la jerarquía y lo arrastramos a cualquier carpeta de nuestro proyecto, como se observa en las figuras 18 y 19.
Luego de eso nos aparece el Prefab en la carpeta, como una miniatura que muestra su apariencia y el nombre. A partir de ahí podemos tomarlo y arrastrarlo hasta la escena para crear todas las copias que necesitemos, como se observa en la figura 20.
Repetimos este proceso para cada pieza individual del laberinto, el pedestal y los portales.
Definir un nuevo Skybox
Ahora vamos a modificar el cielo estándar de la escena. Utilizaremos los archivos descargados de la tienda Asset Store del video anterior, hacer esto era un paso opcional, así que si se tienen los archivos no hay problema, podemos seguir avanzando.
Primero creamos un nuevo Material, lo llamamos «Cielo» y lo seleccionamos para visualizar sus propiedades en el inspector.
Luego hacemos clic en el menú desplegable Shader que por defecto tiene seleccionado «Standard Shader», en su lugar elegimos el Shader «6 Sided Skybox». Esto cambiará totalmente las propiedades del material en el inspector, ahora se observa un inspector como el de la figura 23.
Asignaremos las texturas del paquete Skybox descargado de Asset Store al slot correspondiente del Skybox.
Luego vamos al menú Window > Lighting > Settings para abrir la configuración de la iluminación.
Se abre una ventana como la que se ilustra en la figura 26, la cual coloco al lado del inspector para que no esté flotando.
Hacemos clic en el ícono del círculo con el punto de «Skybox Material» (sobre el que está el cursor en la figura 26) y en la ventana que aparece elegimos el Skybox que acabamos de configurar (figura 27).
Inmediatamente vemos como el cielo que viene por defecto es remplazado por un nuevo cielo de un atardecer con nubes. Con las imágenes apropiadas podemos crear un cielo personalizado para nuestro proyecto.
Ajustar iluminación
En la figura 28 se observa que la luz es demasiado pálida, es decir no parece la luz que se vería en un atardecer. Para corregir esto seleccionamos la fuente de luz en la jerarquía para ver sus propiedades en el inspector (se observa un inspector análogo al que se ve en la figura 33).
En el inspector seleccionamos un color acorde al tono del cielo y ajustamos la intensidad a gusto.
Luego modificamos la rotación de la fuente de luz para que coincida con la posición del sol en el Skybox.
En este punto del video hago una carpeta para colocar los prefabricados pertenecientes al escenario y otras para los objetos. De nuevo hago hincapié en la organización del proyecto.
Finalmente se me ocurre agregar una segunda fuente de luz que apunte directamente hacia abajo y no produzca sombras, de esa forma la escena no se ve tan oscura.
Selecciono la fuente de luz de la jerarquía y presiono CTRL+D para duplicarla, luego la oriento de manera perpendicular al suelo.
En el inspector ajusto los parámetros y en «Shadow Type» selecciono la opción «No Shadows», como se observa en la figura 33. Con esto finalizamos el video 2 de la serie Mi Primer Juego en Unity.
Conclusión
En este video hemos trabajado bastante en el aspecto. Agregamos modelos 3D y texturas, con lo cual aprendimos un poco más sobre los materiales. En el caso de los modelos 3D importados, debemos extraer manualmente los materiales que puedan traer o colocarle materiales nuevos, esta parte está muy conectada con el diseño 3D de la pieza, es decir los materiales que definamos en nuestro software de diseño 3D aparecerán en Unity, quizás tengamos oportunidad de profundizar en este tema más adelante.
Vimos que podemos crear prefabricados de los GameObjects que se encuentran en la jerarquía. Estos prefabricados podremos colocarlos en el mundo fácilmente, en el momento de la edición o en tiempo de ejecución del juego.
Modificamos el cielo que viene por defecto en la escena, en su lugar creamos un material tipo Skybox en el que colocamos texturas para representar los seis lados de la «caja del cielo», esto se comporta como si estuviésemos dentro de un cubo gigante cuyo horizonte se encuentra muy lejos.
Finalmente mejoramos un poco la iluminación de la escena, corrigiendo el color y agregando otra fuente de luz que sume en intensidad pero no produzca sombras.
Introducción
Modelar un rostro 3D puede resultar una tarea desafiante, especialmente cuando recién empezamos en el mundo 3D. En este artículo vamos a ver una forma fácil y práctica de hacer un rostro 3D con una topología bien lograda utilizando Blender, aunque la técnica se puede usar en cualquier software de diseño 3D.
La idea es partir de una imagen de referencia en la que se cuente con la vista frontal y la vista lateral de la pieza que se quiere modelar, pero además que la imagen de referencia muestre información sobre la topología del objeto, es decir dónde están ubicados los vértices, aristas y caras, esto nos permite crear fácilmente el modelo 3D, en este caso el modelo de la cara. Es una práctica muy buena de modelado 3D, especialmente si recién estás empezando, ya que se hacen tareas muy repetitivas y constantemente se está cambiando de vista y de herramientas, puede ayudarte a agilizar el manejo del software.
VÍDEO: Procedimiento para recrear una cara en 3D en Blender a partir de una imagen de referencia
VÍDEO: Timelapse del modelado 3D del rostro en Blender
Topología
La topología es la disciplina que estudia los objetos y sus propiedades geométricas. En los modelos 3D hace referencia al conjunto de vértices, aristas y caras y su interrelación. Es importante que nuestros modelos 3D tengan una buena topología, de esa forma los modificadores, la deformación proporcional, texturización y otras funciones tendrán mejores resultados.
Una buena topología se consigue modelando las piezas con caras de cuatro vértices (quads en inglés) y creando «Edge Loops» que encajen con las curvas naturales del objeto que queremos modelar. En la figura 1 se observan esas caras y edge loops y cómo están distribuidos en el modelo.
En la medida de lo posible hay que evitar el uso de N-gons, que es el nombre con el que se suelen llamar a los polígonos que tienen mas de cuatro aristas.
¿Cómo modelar en Blender a partir de una imagen de referencia?
En Blender podemos colocar imágenes de referencia que se mostrarán de fondo en las vistas ortográficas (las que se acceden con las teclas 1, 3 y 7 del teclado numérico).
En el menú de propiedades (acceso directo tecla N) hay una sección que se llama «Background Images», activamos esta opción y seleccionamos la imagen de referencia. Podemos moverla, rotarla y escalarla, además podemos poner más de una imagen de referencia, como se hace en el video.
Reutilización del modelo del rostro 3D para otro personaje
Marittie es un personaje chibi que hice a partir de un dibujo que hizo mi novia hace algún tiempo.
Al momento de hacerlo tenía un año de experiencia con Blender y aún no estaba familiarizado con el concepto de topología. Sin embargo logré hacer un modelo y en su momento me gustaba mucho.
La topología por supuesto no era buena. El modelo tenía un número muy alto de polígonos, muy mal optimizado. La animación era difícil de lograr. Había irregularidades difíciles de corregir.
Conforme pasó el tiempo fui aprendiendo a mejorar la geometría y llegó el tiempo de rehacer el modelo. Hacía poco tiempo que había hecho el render de la máscara Veneciana (el que se muestra en el timelapse de arriba) y se me ocurrió que podía tomar como base ese modelo para rehacer al personaje. Hice una copia de la máscara y comencé a aplicar deformaciones proporcionales. Como la topología de la cara era buena, fui capaz de transformar la máscara veneciana en el nuevo rostro de Marittie.
Conclusión
La mejora en la topología del nuevo modelo hace más fácil la animación. La herramienta de deformación proporcional tiene mejores resultados y se pueden lograr expresiones muy lindas.
Información actualizada sobre esta entrada
Este artículo pertenece a una serie que consiste en hacer un juego simple en primera persona acerca de encontrar objetos dentro de un laberinto. Es una de mis primeras series de cuando empecé el canal, ahora he mejorado mucho este proyecto y puedes descargar el código fuente para importarlo en tu propio proyecto de Unity. Algún día vamos a hacer un remake de esta serie, suscríbete a mi canal para estar al tanto del nuevo contenido sobre Blender, Unity y programación.
Sígueme en itch.io y descarga el código fuente de este proyecto
PUEDES TESTEAR ESTE JUEGO AQUÍ. TAL VEZ TARDE UN POCO EN CARGAR 🔻
MOVEMENT: WASD CAMERA LOOK: MOUSE
Introducción al artículo original
Este es el comienzo de la serie del Laberinto, en la que crearemos un prototipo simple de juego en primera persona en el que el escenario será un laberinto, mientras vamos viendo todas las herramientas con las que cuenta Unity para crear juegos.
Esta serie es ideal para aquellos que no tienen experiencia con Unity ya que se muestra de todo un poco y sin entrar en detalles, el propósito es mas bien observar todo el proceso de desarrollo para tener una idea general.
Al ejecutar Unity o Unity HUB, nos aparece una ventana en la que podemos crear nuevos proyectos, abrirlos y acceder a los tutoriales.
Vamos a crear un nuevo proyecto 3D, le damos un nombre y elegimos una ubicación en el disco. Todo lo demás es opcional. Cuando todo esté listo creamos el proyecto
Le damos un nombre y seleccionamos el template 3D.
Lo primero que vamos a hacer es crear una nueva escena. En esta versión de Unity, por defecto se nos crea la escena «SampleScene.unity», como se observa en la cabecera del programa en la figura 2.
Para crear una nueva escena hacemos clic en File > Save Scene As…
Le damos un nombre y la guardamos. Al hacerlo se observa en la cabecera el nombre de la nueva escena.
Cada escena tiene su propio diseño independiente de las demás. Por ejemplo podemos usar una escena para el menú principal y otra para el juego.
Todo va a depender de cómo queramos estructurar el juego.
Creación de carpetas
Es importante establecer un sistema de organización para los archivos de nuestro juego en Unity desde el comienzo, porque a medida que avanzamos vamos creando más Scripts, importando más archivos y las cosas se desordenan fácilmente.
Todos los archivos del proyecto se encuentran en la ventana «Project», dentro de una carpeta que se llama «Assets». Esta carpeta se puede encontrar en el directorio que definimos para el proyecto.
Como se observa en la figura 4, al hacer clic derecho se despliega un menú con distintas opciones, vamos a la opción «Create» y elegimos «Folder».
Creamos tantas carpetas como sea necesario para organizarnos, esta parte es personal,
Importar paquetes
Para empezar a hacer un juego en Unity no es necesario crear todo desde cero, podemos valernos de las librerías existentes para comenzar a trabajar en una idea. A continuación vamos a importar Unity Packages (paquetes de Unity) de la librería Standard Assets y de la Asset Store.
Standard Assets – Unity
En la versión de Unity que tenía al momento de grabar el video, se podía importar los paquetes de Standard Assets, una librería que ofrece Unity que cuenta con distintos prefabricados, efectos y scripts que resultan útiles al empezar.
Haciendo clic derecho en la carpeta tenemos la opción «Import Package» donde podemos elegir un paquete que tengamos descargado usando la opción «Custom Package» o podemos elegir algún paquete de Standard Assets.
Si no les aparecen todos los paquetes como se ve en la figura 5, tienen la opción de descargarlos de Asset Store, pero deben tener una cuenta en Unity para poder hacerlo. Más adelante hablamos de eso.
En este caso voy a importar de Standard Assets los paquetes «Characters», «ParticleSystems» y «Utility».
Con el paquete «Characters» podremos colocar en el escenario un prefabricado que tiene implementado un control en primera persona.
ParticleSystems trae algunos efectos interesantes para utilizar, como fuego y humo.
Utility trae algunos scripts útiles como un contador de frames por segundo (fps).
Asset Store – Unity
La tienda virtual de Unity contiene una infinidad de Assets, algunos de pago y otros gratuitos.
Para acceder a la tienda utilizamos la pestaña Asset Store de Unity, si no se encuentra abierta, vamos a Windows > Asset Store o usamos el acceso directo Ctrl+9. Como se observa en la figura 6.
Para utilizar la tienda debemos iniciar sesión en nuestra cuenta (podemos hacerlo desde Unity). Luego utilizando la pantalla de inicio o la barra de búsqueda podemos explorar el contenido.
Con el propósito de ver cómo se usa Asset Store vamos a descargar dos paquetes. El primero se llama «SkyBox» y el segundo «FastMobileBloom», usamos la barra de búsqueda para encontrarlos, en las figuras 7 y 8 se observan las miniaturas de los paquetes.
Para agregarlos a nuestro proyecto entramos en el paquete y ponemos «Descargar», al finalizar la descarga nos aparece la opción «Importar».
Jerarquía del proyecto
Dentro de cada escena estarán definidos todos los elementos del juego, es decir un escenario, objetos que forman parte del mundo, objetos invisibles que sirven para la lógica del juego, interfaz gráfica, etc. Todos estos elementos son conocidos como GameObjects y estarán listados en la jerarquía de nuestro proyecto.
Como se observa en la figura 10, al crear una nueva escena, tenemos dos GameObjects que vienen por defecto. Una cámara y una luz direccional.
Vamos a eliminar la cámara y empezar a agregar objetos al escenario.
Haciendo clic derecho en la jerarquía tenemos la opción de agregar distintos GameObjects, por ejemplo objetos vacíos, primitivas, luces, etc.
Voy a armar un escenario simple con un plano para el suelo y algunos cubos y cilindros.
A medida que vamos agregando más objetos al escenario la jerarquía va creciendo. También es recomendable tener una buena organización desde el principio, colocando nombres apropiados y usando Empty GameObjects para agrupar los objetos.
Observen las figuras 14 y 15. En la primera se ve que ambos cilindros están contenidos por el cubo, ya que están ligeramente más a la derecha y el cubo tiene una flecha para desplegar y colapsar el contenido. En la figura 15 en cambio se observa que están al mismo nivel por así decirlo.
Esto representa la relación de parentesco que existe entre los GameObjects. En la figura 14 se dice que el cubo es el GameObject padre y ambos cilindros son hijos. Esto implica que los cilindros van a estar afectados por ciertos cambios que se apliquen al padre. Por ejemplo si desactivamos el cubo, ambos cilindros también se desactivarán.
Lo mismo ocurre con la componente transformación por ejemplo. La posición de los cilindros se mide respecto de su padre, por lo tanto si movemos al padre, los cilindros se mueven en conjunto.
Materiales
Para aplicar colores y texturas sobre los objetos del mundo se utilizan los materiales. Vamos a crear algunos para ver cómo funcionan. Clic derecho en alguna carpeta del proyecto luego Create > Material, como se observa en la figura 16.
El material se visualiza como una esfera en donde están aplicadas las propiedades del material debemos asignarle un nombre, como siempre mantener el orden desde el primer momento nos beneficia a largo plazo.
Los materiales tienen varios parámetros que lo definen, en nuestro caso simplemente vamos a modificar el color haciendo clic en el recuadro a la derecha de «Albedo». Al hacerlo aparece una paleta de colores donde podemos elegir el color o escribir su código hexadecimal.
Para aplicar un material simplemente lo arrastramos sobre el objeto deseado.
Iluminación
Vamos a seleccionar la luz direccional desde la jerarquía o en la ventana escena.
Por luz direccional se entiende una fuente de luz como el sol, es decir situada en el infinito y que envía todos sus rayos paralelos. Por esta razón mover la fuente o hacerla más grande no afecta a la iluminación de la escena, pero cambiar la rotación si lo hace. Lo vemos en la dirección de las sombras.
Crear una escalera con primitivas
Vamos a hacer este pequeño ejercicio para ver los elementos de la barra de herramientas que tiene Unity, en particular las herramientas que nos permitirán modificar la componente Transform de los GameObjects. Comenzamos creando un cubo en la jerarquía.
Las herramientas mover, rotar y escalar se observan en la figura 22 en las posiciones 2, 3 y 4 respectivamente y se acceden rápidamente usando las teclas «W», «E» y «R» (respectivamente).
Si apretamos la tecla R teniendo seleccionado el cubo, podremos escalarlo utilizando el «Gizmo» de los tres ejes, como se observa en la figura 23.
Lo escalamos en dos direcciones para darle la apariencia de un escalón.
Le aplicamos un material y con la tecla W podemos ubicar el escalón en el escenario.
Podemos duplicar fácilmente el objeto utilizando el acceso directo CTRL+D y con la tecla W elevarlo un poco y desplazarlo hacia atrás.
Podemos repetir este proceso con varios escalones seleccionados.
Vamos a crear un Empty GameObject y llamarlo «Escenario».
Luego seleccionamos todos los objetos y los arrastrámos hacia este nuevo objeto para agruparlos. De esta forma podemos colapsar todo el contenido y la jerarquía se ve más ordenada, como se observa en la figura 30.
Controlador de primera persona
La razón por la que previamente eliminamos la cámara es porque vamos a colocar en la escena el prefabricado «FPSController» de Standard Assets y este ya trae una cámara incorporada. Este prefab se encuentra en el directorio Standard Assets > Characters > FirstPersonCharacter > Prefabs.
Lo llevamos a la escena y lo acomodamos donde nos guste.
Bugs
Ya estamos en condiciones de hacer algunas pruebas, en la parte superior al centro tenemos tres botones.
El botón Play se utiliza para empezar a correr el juego. El segundo botón pausa el juego pero no lo finaliza. El tercer botón sirve para avanzar un sólo frame en el juego.
Al pulsar el botón Play aparece un cartel de error que dice que todos los errores deben arregllarse antes de poder entrar en el modo juego.
Este es un problema con el que nos vamos a encontrar muy seguido, especialmente al principio y suele ser muy frustrante, más aún si estamos aprendiendo a programar.
Para obtener información sobre lo que está pasando tenemos la ventana «Console». Si no se encuentra abierta, la encontramos en el menú «Window».
En la figura 34 observamos una gran cantidad de advertencias pero esto no afecta el funcionamiento del juego, son sugerencias para optimizar el código, advertencias por uso de código obsoleto y demás. Si sólo tuviésemos advertencias podríamos entrar en el modo juego sin problema.
La figura 35 es una captura luego de hacer clic en el botón «Clear», esto limpia las advertencias y deja ver los errores que no se pueden pasar por alto para poder entrar en el modo juego. Estos se muestran con un cartel Rojo.
No hay mucha información sobre el error pero nos basta para entender que hay un archivo que no se encuentra. Si observamos la dirección vemos que está relacionada al paquete Standard Assets y vemos que su dirección comienza con «Assets > Standard Assets > …». En el video hicimos una carpeta llamada «Paquetes Externos» y dentro de ella colocamos el paquete Standard Assets.
Todo parece indicar que hay algún proceso que está buscando archivos de Standard Assets pero dentro de la carpeta Assets, no la carpeta Paquetes Externos, así que muevo la carpeta Standard Assets a la carpeta Assets y el error se soluciona. Ahora si estamos en condiciones de entrar en el modo juego.
Prueba del juego en Unity
El prefab FPS Controller funciona como un juego estándar en primera persona. Avance, retroceso, desplazamientos laterales con las teclas WASD o las flechas. Salto con barra espaciadora, con Shift se puede correr. Con el mouse se controla la vista y tiene sonido de pasos. Es un buen punto de partida para empezar a formar una idea.
Compilación
Ahora vamos a generar una versión standalone del proyecto, es decir un conjunto de carpetas y archivo ejecutable que puede funcionar en nuestro sistema operativo sin necesidad de tener el motor Unity abierto.
Vamos a la pestaña File y hacemos clic en Build Settings, para configurar los parámetros de compilación.
Nos sale la ventana que se ilustra en la figura 39, allí podemos seleccionar la plataforma objetivo.
Si observan en la parte superior es donde están listadas las escenas del juego. En ese momento no tenemos ninguna escena agregada a la compilación.
Haciendo clic en el botón Add Open Scenes vamos a agregar la escena en la que estuvimos trabajando en todo el video. Como se observa en la figura 40.
Ahora solo resta hacer clic en Build And Run y elegir la carpeta donde colocar los archivos generados. Al finalizar el proceso de compilación el juego se ejecuta y nos aparece una ventana en la que podemos seleccionar la resolución y calidad. Le damos al botón Play! y el juego comienza.
Conclusión
En esta primera entrada vimos los primeros pasos al comenzar un juego en unity. Hicimos bastante énfasis en la organización, que nos beneficiará a largo plazo en el desarrollo.
Vimos las escenas de Unity, cada escena es un mundo aparte y contiene una determinada cantidad de elementos o GameObjects que se encuentran listados en la jerarquía del proyecto.
Importamos archivos tanto de la librería Standard Assets como de la tienda Asset Store. Al principio lo más importante es tratar de darle forma a las ideas que tenemos, para esto los assets de las librerías nos facilitan las cosas.
Vimos algo sobre la relación de parentesco que existe entre los GameObjects y cómo los cambios que se aplican sobre un objeto padre también impactan en sus objetos hijo.
Creamos materiales que sirven para dar color y textura a los objetos.
La fuente de luz direccional nos sirve para iluminar una escena como lo haría el sol, las sombras se proyectarán en función de la rotación que tenga esta fuente de luz.
Hicimos una escalera simple utilizando las primitivas que se pueden crear con Unity y aplicándoles transformaciones, es decir cambios de escala, rotación y posición.
Colocamos el prefabricado de Standard Assets «FPSController» que es un control en primera persona. Rápidamente ya tenemos un personaje que puede recorrer el escenario, correr y saltar.
En el proceso hubo errores que debimos solucionar para poder entrar en el modo juego. La depuración de errores es una tarea difícil cuando empezamos a programar, pero con la práctica se van cometiendo menos errores y resulta más fácil corregirlos.
Finalmente hicimos una compilación ejecutable desde el sistema operativo. Existe una gran cantidad de plataformas a las que podemos exportar nuestro juego en Unity. En principio vamos a exportar a Windows y Android.
Introducción
Mucho antes de empezar con la programación y el mundo de los videojuegos solía ser carpintero, en ese período de mi vida fue cuando cree junto a un amigo el infame gabinete para PC hecho en fibrofácil.
Historia
Llevaba un tiempo fabricando cosas en mdf o fibrofácil como se conoce en donde vivo, había hecho varios sets de ajedrez y unas cajas que mi novia había decorado con decoupage, me gustaba bastante y tenía facilidad. Un día estaba en clase de química en la facultad y le muestro a un amigo los trabajitos que había hecho. Él se interesa y me cuenta que necesitaba una caja provisional para tapar su computadora ya que aún no había conseguido un gabinete y su computadora la cubría con una caja de cartón.
En la figura 1 se muestra la estructura que tenía hasta el momento para la placa madre y fuente de alimentación.
Entonces la idea era hacer una caja que contenga eso para prevenir que se ensucie.
Diseño del gabinete MDF
Mi amigo hizo un diseño que le parecía conveniente para la ventilación y a partir de eso hice un diseño 3D usando SolidWorks (en ese momento no conocía Blender), esa fue mi primera aproximación con el modelado en 3D sin contar que de chico hacía mapas para el Counter Strike usando Entidad 3D.
Con el diseño 3D pudimos hacer unos renders y ajustarlo hasta que quedó como mi amigo quería. A partir de ese diseño 3D hice un plano de 6 vistas para los cortes de las piezas (creo que por ese tiempo también había hecho dibujo técnico en la facultad).
Tomando como base los planos, dibujé las seis piezas sobre una placa de mdf de 5 mm de espesor, en esta parte se tomaron bien las medidas para que todo quede a escuadra.
Hice todos los agujeros en los cortes internos para que entre la hoja de la caladora.
Los cortes simples los hice utilizando una caladora de mano y los cortes precisos con una caladora de banco.
Los cortes quedaron a medida, solo que no tan rectos porque fueron hechos a pulso.
En la figura 8 se ve que la estructura ya iba tomando forma.
Pegué las tres piezas usando cola y luego apliqué un prensado para que la estructura quede bien firme, a continuación se observan las herramientas de prensado.
Observen como la prensa roja de metal (una prensa propiamente dicha) se encarga de mantener armada la caja de Monopoly, de esa forma la estructura no colapsó bajo su propio peso.
Para las bahías de los discos hicimos una estructura de tres pisos, en la siguiente figura se muestra la idea para el diseño.
La pieza la construimos también con mdf de 5 mm y una capa de pintura acrílica roja.
Luego empezamos a pensar en la decoración de la caja, porque tenía que tener aunque sea una capa de pintura. En ese momento no sabía tanto de componentes de computador y marcas como ahora, sin embargo propuse algunos diseños que le gustaron.
El logo de Republic of Gamers para una placa MSI.
Habíamos comprado unas empanaditas de carne para comer y se estaba haciendo tarde.
Aquí se puede ver que estoy dando los últimos retoques. Nuestro gabinete mdf estaba casi terminado.
Atornillamos los coolers en su lugar, colocamos la estructura con la placa madre, la fuente, los discos en el interior y finalmente las dos piezas de acrílico que entraban en unas ranuras. Este fue el resultado final:
Conclusión
Logramos terminar el gabinete mdf y mi amigo tuvo una cajita para albergar su computadora. Fue algo temporal hasta que finalmente consiguió un gabinete de pc.
A mi parecer las dimensiones estaban bastante exageradas, pero mi amigo estaba preocupado (y con razón) por la refrigeración. En un gabinete de metal el calor se disipa en parte por la conductividad térmica. Además de que proporciona protección a los circuitos frente a ruidos electromagnéticos.
Sin embargo si tenemos en cuenta el hecho de que antes tapaba la computadora con una caja de cartón, el gabinete mdf fue una pequeña mejora.
Esta página utiliza cookies para analíticas y ads, continua navegando en él si estás de acuerdo. Ajustes de CookiesACEPTAR
Política de Privacidad y Cookies
Privacy Overview
This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are as essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.