Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation since 04/23/2012 in all areas

  1. 12 points
    Después de la mega-paliza que me pegué haciendo el supervídeo de BasicScripts, vuelvo a la carga con una nueva batería de tutoriales. En esta ocasión, voy a cambiar completamente de tema y dejar de lado los FPS y tirar por el apasionante mundo de la simulacion de coches. He subido un vídeo de presentación de tutorial y en los próximos días empezaré a hacer los tutoriales propiamente dichos. Espero que os guste: Acutalización, los tres primeros vídeos de este tutorial: Acutalización 2, los cuatro vídeos que siguen: Actualización 3: Resto de los vídeos hasta el final de la serie. https://www.youtube.com/watch?v=NlzoKl0Fwrs https://www.youtube.com/watch?v=D-sSmmKAXso https://www.youtube.com/watch?v=WpWQ8-LztXc Saludos.
  2. 11 points
    Hola a todos. A petición de un usuario voy a aportar un script para controlar un objeto mediante botones (GUITextures) en Android o dispositivos móviles. Es un script muy simple con cuatro botones, pero pienso será de gran ayuda para el que esté comenzando con esto de los móviles. public var boton_abajo: GUITexture; public var boton_izquierda : GUITexture; public var boton_derecha: GUITexture; private var boton_arriba_pulsado : boolean; private var boton_abajo_pulsado : boolean; private var boton_izquierda_pulsado : boolean; private var boton_derecha_pulsado : boolean; public var speed : float = 10.0; function Awake(){ SituarControles(); } function Update(){ if(Input.touchCount > 0){ for (var i = 0; i < Input.touchCount; ++i) { if(boton_arriba.HitTest(Input.GetTouch(i).position)){ boton_arriba_pulsado = true; }else if(boton_abajo.HitTest(Input.GetTouch(i).position)){ boton_abajo_pulsado = true; }else if(boton_izquierda.HitTest(Input.GetTouch(i).position)){ boton_izquierda_pulsado = true; }else if(boton_derecha.HitTest(Input.GetTouch(i).position)){ boton_derecha_pulsado = true; } } } //UNA VEZ HEMOS RECIBIDO LAS ENTRADAS. ACTUAMOS!!! if(boton_abajo_pulsado){ transform.Translate(-Vector3.up * speed * Time.deltaTime); }else if(boton_arriba_pulsado){ transform.Translate(Vector3.up * speed * Time.deltaTime); } if(boton_derecha_pulsado){ transform.Translate(Vector3.right * speed * Time.deltaTime); }else if(boton_izquierda_pulsado){ transform.Translate(-Vector3.right * speed * Time.deltaTime); } //LO PONEMOS A FALSE PARA COMPROBAR EN EL SIGUIENTE Update() SI SE SIGUEN PULSANDO O NO. boton_derecha_pulsado = false; boton_izquierda_pulsado = false; boton_arriba_pulsado = false; boton_abajo_pulsado = false; } function SituarControles(){ //CONTROL ABAJO boton_abajo_pulsado.transform.position = Vector3.zero; boton_abajo_pulsado.transform.localScale = Vector3.zero; boton_abajo_pulsado.guiTexture.pixelInset.width = Screen.width/7; boton_abajo_pulsado.guiTexture.pixelInset.height = boton_abajo_pulsado.guiTexture.pixelInset.width; boton_abajo_pulsado.guiTexture.pixelInset.x = Screen.width - (boton_abajo_pulsado.guiTexture.pixelInset.width * 1.1); boton_abajo_pulsado.guiTexture.pixelInset.y = Screen.height/30; //CONTROL ARRIBA boton_arriba_pulsado.transform.position = Vector3.zero; boton_arriba_pulsado.transform.localScale = Vector3.zero; boton_arriba_pulsado.guiTexture.pixelInset.width = Screen.width/7; boton_arriba_pulsado.guiTexture.pixelInset.height = boton_arriba_pulsado.guiTexture.pixelInset.width; boton_arriba_pulsado.guiTexture.pixelInset.x = Screen.width - (boton_arriba_pulsado.guiTexture.pixelInset.width * 1.1); boton_arriba_pulsado.guiTexture.pixelInset.y = Screen.height/3; //CONTROL DERECHA boton_derecha_pulsado.transform.position = Vector3.zero; boton_derecha_pulsado.transform.localScale = Vector3.zero; boton_derecha_pulsado.guiTexture.pixelInset.width = Screen.width/7; boton_derecha_pulsado.guiTexture.pixelInset.height = boton_derecha_pulsado.guiTexture.pixelInset.width; boton_derecha_pulsado.guiTexture.pixelInset.x = boton_derecha_pulsado.guiTexture.pixelInset.width + boton_derecha_pulsado.guiTexture.pixelInset.width/1.8; boton_derecha_pulsado.guiTexture.pixelInset.y = Screen.height/30; //CONTROL IZQUIERDA boton_izquierda_pulsado.transform.position = Vector3.zero; boton_izquierda_pulsado.transform.localScale = Vector3.zero; boton_izquierda_pulsado.guiTexture.pixelInset.width = Screen.width/7; boton_izquierda_pulsado.guiTexture.pixelInset.height = boton_izquierda_pulsado.guiTexture.pixelInset.width; boton_izquierda_pulsado.guiTexture.pixelInset.x = Screen.width/50; boton_izquierda_pulsado.guiTexture.pixelInset.y = Screen.height/30; } USO: Este script se lo ponen al objeto que vayan a mover. Luego se crean 4 GUitextures y se le agregan al script desde el inspector Saludos
  3. 10 points
    Muchos lo sabréis y otros no, pero hay una lista de recursos bastante tocha hecha en zeef.com de recursos para el desarrollador de videojuegos. Espero que os sea de utilidad! https://game-development.zeef.com/daniel.cuadrado.gonzalez
  4. 8 points
    Enlace de descarga: https://app.box.com/s/384vkwhfosk9zgzpftphq3oi35yifhpb Para este sistema de Save/Load necesitamos crear un prefab de la entidad. El prefab se necesita para instanciar/crear un nuevo GameObject de la forma más sencilla. El sistema de guardado consta de una clase estática llamada GameData que almacena una sola instancia MonoBehaviour(script) de cada GameObject dentro de una ArrayList, y dispone de las funciones Save y Load: using UnityEngine; using System.Collections; using System.IO; using System.Runtime.Serialization.Formatters.Binary; public static class GameData { public static string file = "GameData.dat"; public static ArrayList Data = new ArrayList(); //Aqui se almacenaria todos los datos como objetos public static bool Save(){ FileStream fs = new FileStream(file, FileMode.Create); BinaryFormatter formatter = new BinaryFormatter(); ArrayList arrayList = new ArrayList(); foreach(object data in Data){ ISaveLoad script = (ISaveLoad) data; arrayList.Add(script.GetData()); } try { formatter.Serialize(fs, arrayList); } catch (System.Runtime.Serialization.SerializationException e) { UnityEngine.Debug.Log("Failed to serialize. Reason: " + e.Message); return false; } finally { fs.Close(); } arrayList.Clear(); arrayList = null; formatter = null; fs = null; return true; } public static bool Load(){ if(!File.Exists(file)) return false; FileStream fs = new FileStream(file, FileMode.Open); ArrayList arrayList; try { BinaryFormatter formatter = new BinaryFormatter(); arrayList = (ArrayList) formatter.Deserialize(fs); formatter = null; } catch (System.Runtime.Serialization.SerializationException e) { UnityEngine.Debug.Log("Failed to deserialize. Reason: " + e.Message); return false; } finally { fs.Close(); } Data.Clear(); //Instanciar GameObjects a escena foreach(object data in arrayList){ EntityData entityData = (EntityData)data; entityData.OnLoad(UnityEngine.Object.Instantiate<GameObject>(Resources.Load<GameObject>(entityData.ResourcesPath))); } arrayList.Clear(); arrayList = null; fs = null; return true; } } Uso la instancia de un script como referencia del GameObject, y no una clase serializada directamente, porque es constante durante todo el tiempo de juego. Tampoco utilizo el GameObject directamente como referencia, para que este sistema de guardado pueda ser utilizado por cualquier tipo de script(SOLO UN SCRIPT por GameObject podrá implementar el sistema de guardado). Este único script recoge los datos de los componentes y otros script del GameObject. Para poder guardar los datos del juego de forma generalizada, utilizo una clase base serializada llamada EntityData con el campo ResourcesPath y la funcion OnLoad: [System.Serializable] public class EntityData{ public string ResourcesPath; public virtual void OnLoad(GameObject gameObject){} } Y además, necesito una interfaz para poder extraer los datos de los GameObjects, con la funcion GetData(): interface ISaveLoad{ object GetData(); } UTILIZACION Como he dicho, antes de nada, es necesario crear un prefab de la entidad/GameObject que alojaremos en la carpeta Resources. A continuación, dentro de algún script del GameObject a guardar(solo un script del GameObject puede implementar este sistema): 1) Creamos una clase derivada de EntityData. Esta clase hereda ResourcesPath y la funcion OnLoad necesaria para la carga de la escena, y añadiremos los datos que queramos guardar del GameObject. Por ejemplo: [System.Serializable] public class Data : EntityData{ [HideInInspector] public float px,py,pz,rx,ry,rz,sx,sy,sz; public int vida = 100, experiencia = 0; public override void OnLoad (GameObject gameObject) { Transform transform = gameObject.GetComponent<Transform>(); transform.position = new Vector3(px,py,pz); transform.eulerAngles = new Vector3(rx,ry,rz); transform.localScale = new Vector3(sx,sy,sz); ScriptEntidad1 script = gameObject.GetComponent<ScriptEntidad1>(); //Transformamos el object en la clase de datos de la entidad script.datos = (ScriptEntidad1.Data) this; } } public Data datos; He creado una clase llamada Data, derivada de EntityData, donde almaceno los datos del Transform y dos campos de vida y experiencia. En la funcion OnLoad asigno estos valores a los componentes, es decir, al Transform y al Script al que he vinculado los datos, en este caso al script 'ScriptEntidad1'. 2) Añadimos el script a la lista de GameData desde la funcion Start() de Unity, y los eliminamos al destruir el GameObject desde la funcion OnDestroy() de Unity: void Start () { //Añadir GameObject a la lista GameData.Data.Add(this); } void OnDestroy(){ //Eliminar GameObject de la lista GameData.Data.Remove(this); } 3) Añardir la funcion GetData de la interfaz ISaveLoad: public class ScriptEntidad1 : MonoBehaviour, ISaveLoad { object ISaveLoad.GetData(){ //Actualizar Datos Transform Vector3 temp = this.transform.position; this.datos.px = temp.x; this.datos.py = temp.y; this.datos.pz = temp.z; temp = this.transform.eulerAngles; this.datos.rx = temp.x; this.datos.ry = temp.y; this.datos.rz = temp.z; temp = this.transform.localScale; this.datos.sx = temp.x; this.datos.sy = temp.y; this.datos.sz = temp.z; return this.datos; } } Si quereis ver el codigo completo del script: using UnityEngine; using System.Collections; public class ScriptEntidad1 : MonoBehaviour, ISaveLoad { [System.Serializable] public class Data : EntityData{ [HideInInspector] public float px,py,pz,rx,ry,rz,sx,sy,sz; public int vida = 100, experiencia = 0; public override void OnLoad (GameObject gameObject) { Transform transform = gameObject.GetComponent<Transform>(); transform.position = new Vector3(px,py,pz); transform.eulerAngles = new Vector3(rx,ry,rz); transform.localScale = new Vector3(sx,sy,sz); ScriptEntidad1 script = gameObject.GetComponent<ScriptEntidad1>(); //Transformamos el object en la clase de datos de la entidad script.datos = (ScriptEntidad1.Data) this; } } public Data datos; object ISaveLoad.GetData(){ //Actualizar Datos Transform Vector3 temp = this.transform.position; this.datos.px = temp.x; this.datos.py = temp.y; this.datos.pz = temp.z; temp = this.transform.eulerAngles; this.datos.rx = temp.x; this.datos.ry = temp.y; this.datos.rz = temp.z; temp = this.transform.localScale; this.datos.sx = temp.x; this.datos.sy = temp.y; this.datos.sz = temp.z; return this.datos; } void Start () { //Añadir GameObject a la lista GameData.Data.Add(this); } void OnDestroy(){ //Eliminar GameObject de la lista GameData.Data.Remove(this); } }
  5. 8 points
    Lost Hope Hola a todos , somos Somber Pixel! Estamos desarrollando un juego survival horror hecho a base de pixel art llamado Lost Hope Lost Hope es un survival horror donde se puede explorar libremente diferentes lugares de una ciudad y tomar decisiones para poder sobrevivir a una catástrofe que ha traído consigo a mutantes . Hemos tomado bastante información sobre otros survival horrors , como silent hill o los primeros resident evil , así como algunos proyectos indie que hemos visto . Acerca del juego Vista General Que harías si de repente las personas a tu alrededor comienzan a convertirse en violentos mutantes? Esperando en casa por unos días hasta que todo se solucione puede ser una opción , lo cual ya lo has hecho por un tiempo y ahora estas sin nada de suministros para poder sobrevivir. Lo siguiente que pasa por tu cabeza es : tu objetivo debe ser escapar de la ciudad y ( si tu curiosidad es mucha) descubrir que esta pasando actualmente. Por supuesto, estamos trabajando en darle personalidad a cada uno de nuestros NPC con los que te encontraras , de momento no hablaremos mucho de esto ya que podrías frustrar la experiencia del juego para muchos , en resumen , tu objetivo principal sera : sobrevivir y escapar de la ciudad . Características Fluido y divertido sistema de combate Esto no quiere decir que sea fácil ! queremos que sientan el horror de tener un mutante frente a ustedes. Así que si quieres jugar a lo Rambo aquí .... terminaras muerto en muchas piezas por un mutante ya que las balas serán escasas. También habrá combate cuerpo a cuerpo, todo acción sera para sobrevivir. *La siguiente imagen es un trabajo en proceso (WIP) , es para dar una idea del juego , las calles estarán mucho mas detalladas en la versión final. Exploración y decisiones Explora una ciudad entera que tendrá diferentes entornos detallados desde el principio , que podrás recorrer bajo tus propio riesgo. Podrás entrar en cada edificio de la ciudad. Mirar a cada sobreviviente que estará lleno de una personalidad interesante , hacerles favores o hasta llegar a matarlos ... espera , Que? eso no destruiría el desarrollo de la historia y lo volvería genérico? No , esto sera parte del juego , en la vida real debes hacer todo lo posible por sobrevivir a una catástrofe con mutantes, pero todo en esta vida tiene consecuencias , no ? Enemigos mortales que te harán sentir bendecido por llevar una vida normal sin ellos queriéndote matar Cada mutante es diseñado con una estrategia de combate que vaya a juego con su diseño , cierto , todos te querrán matar .Algunas veces es mejor eludirlos a entablar combate y así encontrar una ruta alternativa. Muchos objetos para coleccionar Y mucho mas Tenemos mas aspectos que queremos mostrar en este tema , pero aun nos falta retocarlos. Estaremos posteando de manera regular ! y acerca del audio , lo cubriremos en un futuro cercano ya que es una parte muy importante del juego. Conoce al equipo Solos somos dos personas en Somber Pixel , pero pondremos todo nuestro esfuerzo y tiempo en este juego ! Izquierda: Adolfo Jungbluth(Programador) Derecha: Arturo Anci(artista Pixel art ) Y la parte mas importante ...el feedback de los usuarios ! Apreciaríamos muchos cada idea que se les venga a la cabeza o critica que nos ayude a mejorar así sera el juego que ustedes y nosotros queremos al final ! Un poco tarde , pero santa les deja un pequeño mensaje navideño Mas información Twitter: Somber Pixel: @SomberPixel Adolfo: @adolfojo777 Arturo: @Artan0728 Tumblr: http://somberpixel.tumblr.com/ Facebook: https://www.facebook.com/SomberPixel O directamente en este tema o MP !
  6. 8 points
    Hola gente de UnitySpain. Me complace comunicaros que hemos terminado un nuevo proyecto para Android. https://play.google.com/store/apps/details?id=com.CodeLimit.MarioCrossy Actualización: https://itunes.apple.com/es/app/fun-run-cross-hero/id1020639994?mt=8 Curioso el caso del video con apenas 100 visualizaciones y 200 descargas del juego. El juego es un clásico runner endless pero cogiendo una perspectiva isométrica tal cual uno de los clásicos de Mario. La idea es coger varios conceptos que están muy de moda en muchos juegos actuales, pero usando una propuesta distinta. * Es decir, tendremos varios personajes a elegir, con varias habilidades que aún se encuentran en desarrollo. Ya tenemos algunos disponibles como jugar con Marcos (xD) con doble salto o Donatello con disparo especial * Generación random de escenario, incrementando la probabilidad de zonas difíciles en función de la distancia recorrida. * Generación random de enemigos en función de la distancia y de las condiciones climatológicas. * Concepto visual imitando a Minecraft y usando personajes clásicos obviando los nombres, esperamos conseguir un reclamo visual y llegar a tener algunas descargas decentes. * Drop de items actuales de monedas y munición, a lo largo de la semana esperamos tener los items para craftear armaduras y botas que mejoren los stats de cualquier personaje. Nos quedan que pulir algunas cosas, ajustar mas finamente las partículas y otras mas, pero antes de pegarnos un curro de 6 meses y estamparnos contra la pared hemos publicado para ver la aceptación del publico. Esperamos ansiosos vuestros comentarios, para poder mejorar en la medida de la posible el juego y convertirlo en lo mas divertido posible. Cabe destacar que los records he intentado protegerlos para que haya mas competitividad, tampoco os pido que superéis el mío, ya que la mayoría del foro no tienen porque tener destreza jugando y si programando, cosa que para mi es al revés Y_Y Por favor, si contesto algún comentario, no es que no agradezcamos las valoraciones y que también nos gusta compartir nuestros puntos de vista. GRACIAS por poder trabajar con Gustavo Schreyer, un excelente diseñador, y mejor persona. Los audios hemos reutilizado alguna cosa de Sergio Gonzalez, últimamente no logramos contactar con el, estuvo enfermo recientemente y perdí su teléfono, si alguien lo tiene por favor que contacte conmigo por privado.
  7. 8 points
    ¡Hola a todos! Acabo de terminar de grabar una serie completa de tutoriales (de unas 14 horas de vídeo en total) en la que explico los conceptos básicos de programación usando C# en Unity. Este curso está especialmente diseñado para personas que nunca han programado, así que espero que sea una buena forma de empezar a escribir código en C#. Esta es la lista de reproducción de este curso: http://goo.gl/nlhTyv Y este es el enlace de mi canal: http://www.youtube.com/juande Echadle un vistazo a la siguiente presentación para ver si se adapta a vuestras necesidades. Espero que os resulte interesante. Estos son otros tutoriales que he publicado en este foro:
  8. 8 points
    ¡Hola a todos! En este curso se desarrolla (desde el principio, hasta el final, y paso a paso) un juego tipo "Infinite Runner" en 2D con Unity 4.3. Os dejo por aquí un vídeo introducción del curso para que evaluéis si os interesa o no. Esta es la lista de reproducción de este curso: http://goo.gl/k7jCOVY este es el enlace de mi canal: http://www.youtube.com/juande Echadle un vistazo a la siguiente presentación para ver si se adapta a vuestras necesidades. Estos son otros tutoriales que he publicado en este foro: PD: En su día también hice un curso completo sobre cómo desarrollar un juego de realidad aumentada utilizando el plugin de Vuforia para Unity 3.5. Si os interesa aprender a hacer algo con la realidad aumentada, lo podéis encontrar también en mi canal. ¡Saludos!
  9. 7 points
    Mi primer vídeo juego en Unity 3D Personal. También hecho con MakeHuman y blender. Mi blog
  10. 7 points
    Hola gente les dejo un link a mi curso de youtube, totalmente gratuito y disponible para la comunidad. Esta totalmente actualizado al 2020 y hecho por mi, soy programador con titulo universitario y 10 años de experiencia en unity! El curso esta dividido en niveles de dificultad, Comenzando para gente que nunca toco unity y terminando con contenido muy avanzado como creacion de framework propios para multiplayer, entre otras cosas. Para que los usuarios mas avanzados puedan saltearse las partes que no les sirve y explorar mas fácilmente el contendio. Son mas de 200 videos, con muchisimas horas de grabacion que complete con la intención de subir a udemy. Al terminarlo cambie de parecer y ahora lo estoy subiendo de forma gratuita a youtube. Se sube 1 video cada dia de forma atomatica, y ya estan todos los videos seteados para subirse a youtube de forma automatica a este ritmo. Link: https://www.youtube.com/channel/UCl3p_fKnx2-GIUWVbiDAcMg Sin mas, espero verlos por mi canal y que les sirva el curso. Un saludo!!
  11. 7 points
    Hola, ahora que he empezado el proceso de subir un segundo juego a la playstore le he encontrado utilidad a los post que escribí al subir el primero, ya que me están facilitando mucho el trabajo. Os dejo los enlaces con una pequeña explicación y espero que puedan ser de ayuda a todos aquellos que hacen sus primeras subidas a la tienda de Google. Como subir un juego a la playstore. Aparte de describir el proceso, se indica lo que tendríamos que tener preparado previamente, como los iconos, o una descripción corta y una larga, pantallas, un vídeo… Como firmar un apk de unity para subirlo a la play store. Lo más importante: NO PERDÁIS NUNCA DE LOS JAMASES LA FIRMA. Incorporando Google logros con Google Play Services. Aparte de publicar el juego creo que es una buena idea aprovechar las diversas posibilidades que nos ofrece Google, los logros es una de ellas, y pueden ayudar a motivar al jugador. Como crear un tablero de puntos para Unity con Google Leaderboard. Otro de los servicios que nos ofrece Google y podemos aprovechar: el tablero de puntos! Són post muy simples, donde se explica el proceso más sencillo. Por ejemplo en el de subida no pasamos por Alpha y Beta, ni creamos un grupo de usuarios Betas. Espero que sirvan a todos aquellos que suben su primer juego! Suerte… y a por los Euruuuuuuus!!!
  12. 7 points
    ABRAMELIN GAMES Injection π23 Survival-horror clásico Inspirado en una pequeña localidad de Málaga. Jugabilidad orientada a resolver puzzles, exploración y supervivencia. 4 modos de cámara: 1ª persona, 3ª persona (camara libre y autocam) y camaras fijas (survival-horror clásico). Juego no recomendado para menores de 18. Plataforma: PlayStation 4, Windows (x64) Desarrollado por: J.A.M. (Abramelin Games) Colaboraciones: Abramelin logo, bocetos y cover art por Danilo 'Do Burundanga' Supervisión de código, sistema Autotarget 3ª persona, Autocam y sistema IK por Francisco Javier Tejada. Guía de optimización: LightBug Luces volumétricas open source por Michal Skalsky Actores de voces: Bernardo Casado (grabaciones cintas, doctor1) Jonathan Casquete (ex-militar, policia1) Virginia Montero (niño walkman) Miguel Flames (sacerdote2, policia2) Javi Ruiz (personaje principal) Luis Alberto Martin (doctor2, magnate) Pablo Ibañez (sacerdote1) Ruth pascual (doctora) Diego Orellana (enterrador, enfermero, guardaespaldas) Carlos Cremades (dueño del club) Francisca Rey (mujeres del club, ermitaña) Jose M. Sancho (profesor) http://abramelingames.blogspot.com/ www.abramelingames.com https://twitter.com/AbramelinGames
  13. 7 points
    Trigonometría con Mathf Hola a todos, Me dispongo a hacer unas explicaciones de trigonometría Mathf y como funciona, y algo de explicaciones matematicas al respecto. Explicare los metodos mas importantes de la trigonometría. Explicare primero los arcos de coseno, seno y tangente. explicando en ellos el coseno, seno y tangente a su vez. luego mostrare como funciona Mathf.cos, Mathf.sin y Mathf.tan aparte sin explicar matematicamente cada uno, ya que han sido explicados junto a sus arcos. Mathf.Abs Este es sencillo y facil de entender asi que no me entretengo, Abs retorna el valor absoluto de un valor X Debug.Log(Mathf.Abs(-2045.34f)); //Vemos que estamos pasando el valor -2045.34f, el valor retornado sera 2045.34 //Si el valor que le pasamos a Mathf.Abs() es -10, este nos retornara 10. //En definicion, Abs retornara el valor positivo. Mathf.Acos Esta devuelve el Arcocoseno de un valor, recordar que lo devuelve en radianes. Que es coseno: Quiero explicar antes el coseno para poder entender mejor el arcocoseno. (Al igual que haré con seno, el codigo de ejemplo lo pondre para Mathf.Cos()) el coseno es la razon entre: El cateto adyacente (b) a dicho ángulo y la hipotenusa (c) en un triangulo rectangulo. esto quiere decir que cos α = b / c donde α es el valor angular con un dominio de [0,π]. (cuando hablamos de dominio, queremos decir un rango entre un minimo y un maximo, en este caso el minimo es 0 y el maximo 3.14159265359) Esta es la grafica de coseno: Que es Arcocoseno: Por definicion es la funcion recíproca de coseno, Esta es el arco cuyo coseno es alfa. arcocoseno restringe el dominio de la funcion coseno a (x) [-1,1] donde su codominio (α) [0, π]. Donde x es el valor comprendido entre -1 y 1 de la linea que vemos en la imagen, y α es la aceleración angular por unidad de tiempo. float x = ; //0 es exactamente es exactamente la bisectriz del primer y el tercer cuadrante de la grafica de arcocoseno. Debug.Log(Mathf.Acos(x)); //Devolvera (1/2)π radianes, que es 1,57 radianes. que en grados es 0. //Si X fuese 0.7, Devolveria (1/4)π radianes, que es 0,785 radianes. que son 45 grados. La tabla de valores comunes es: Valor dominio X: -1 -√2/2 -1/2 0 1/2 √2/2 1 Angulos: 180 135 120 90 60 45 0 Radianes: π 3/4π 5/6π 1/2π 1/3π 1/4π 0 Que son Radianes: El radian es la unidad de ángulo plano, en el sistema de medidas, 1rad = r. donde r es el radio de la circunferencia. y la circunferencia siempre vale 2π radianes. Esto quiere decir que 1 radian en valor decimal es equivalente la la longitud del radio. os dejo una imagen que aclara bastante la mente. Mathf.Approximately Segun la referencia oficial de unity: (Este metodo lo añado por que me parecia interesante) //En vez de: if(1.0f == 10.0f / 10.0f)... //Hacer esto: if(Mathf.Aproximately( 1.0f, 10.0f / 10.0f )... (Supongo que esto es mejor usarlo con valores float largos como pueda ser π.) Mathf.Asin Este metodo devuelve el arcoseno de un valor, Recordar que lo devuelve en Radianes. Que es seno: Como con arcocoseno ya explique el coseno, con arcoseno explicare el seno. el seno es la razon entre: El cateto opuesto (a) a dicho ángulo y la hipotenusa (c) en un triangulo rectangulo. esto quiere decir que sen α = a / c (La diferencia con coseno es que coseno usa cateto adyacente, y este usa el opuesto al ángulo) donde α es el valor angular con un dominio de [0,π]. Esta es la grafica de seno: Ahora que sabemos que es el seno: Que es Arcoseno: Al igual que arcocoseno es la funcion recíproca de coseno, arcoseno es la funcion recíproca de seno. Lo que quiere decir que: SI arcsen x = α ENTONCES sen α = x recordar tambien que se escribe arcsen o sen-1 Es el arco cuyo seno es α. (Es como el espejo de arcocoseno antes explicado) arcoseno restringe el dominio de la funcion seno a (x) [-1,1] donde su codominio (α) [-π/2, π/2]. Os mostrare ahora una imagen de como se comportan seno y arcoseno en una grafica: La gráfica de la función arcoseno es simétrica a la de la función seno respecto a la recta bisectriz del primer y tercer cuadrante (y=x) float x = .5f; //.5f es el equivalente a 1/2 Debug.Log(Mathf.Asin(x)); //Devolvera 1/6π radianes que es 0,52 y son 30 grados. Mathf.Atan El metodo devuelve en arcotangente de un valor, recordar que lo devuelve en radianes. Que es la Tangente: La tangente la razon entre los catetos de un triangulo rectangulo. tan α = a / b Siempre como dividendo es el cateto opuesto, y como divisor el cateto adyacente. Vamos a recordar que sen α = a / c y que cos α = b / c por lo tanto la tangente de α se puede expresar como tan α = sen α / cos a Para comprender el concepto de tangente, graficamente vista en la imagen anterior, imagina una linea que su punto 0 nace desde D y tiende a infinito. El dominio de la tangente es (x) [-∞,∞], donde su codominio (α) [-π/2, π/2]. (Tranquilos esta funcion no estan necesaria en un principio como seno y coseno, asi que no os preocupeis si os resulta mas compleja) Que es Arcotangente: En este caso es la función recíproca de tangente. Al igual que con arcoseno y arcocoseno, arcotangente es el arco cuya tangente es α. En notacion matematica se puede escribir arctan o tan-1. Uso con unity de estas funciones Vale, ahora que sabemos la teoria, queda lo mas interesante que es la practica de estos conceptos en unity, y aplicaciones varias. El metodo que utilizare para mostrar los ejemplos sera con imagenes y codigo para que veamos la facilidad del asunto. (Recordar tambien que el objetivo es entender estos conceptos, para que podais usarlos a vuestro libre albederio) En este ejemplo, vamos a ver como saber los grados que tiene que rotar un objeto para mirar a otro. (Aunque esta funcion ya trae incorporada unity como Transform.LookAt() aquí explicare como funciona internamente) Lo primero que hay que saber es como conseguir la distancia entre dos puntos del plano de unity. (Yo trabajare con Vectores de dos dimensiones, "Vector2") Vector2.Distance(Vector2 a, Vector2 b); //Distancia entre los dos vectores. //Es lo mismo que hacer: Vector2 a = new Vector2(10, 11); Vector2 b = new Vector2(5, 8); float dist = (a - b).magnitude; Debug.Log(dist); Ahora en el proyecto creamos dos objetos, recuerdo que estoy trabajando en 2D, en 3D seria lo mismo pero jugando con Vector3, recordar que solo rotamos en el eje Y. Como vemos he creado dos objetos en un plano bidimensional, son dos sprites, el azul llamado objeto1 su posicion es: X=0 Y=-3.5, el negro y rojo llamado objeto2 su posicion es X=4 Y=-1. Como veis he dibujado un triangulo rectangulo a partir del punto A (Objeto1) y punto B (Objeto2) ahora tenemos la incognita de C que es sencilla, es la posicion Y de A y la posicion X de B Para encontrar la posición de C en Unity: public Transform A, B; //Aqui añadiremos los objetos de nuestra escena desde el inspector. void Start () { Vector2 C = new Vector2(B.position.x, A.position.y); //C es la posicion X del objeto2 y la posicion Y del objeto 1 } Ahora ya tenemos los 3 puntos de nuestro triangulo imaginario. Ahora hay que saber la distancia de h, de ca y de co Aunque para sacar el coseno que es lo que necesitamos, no nos hacefalta co, ya que solo necesitamos cateto adyacente e hipotenusa. public Transform A, B; //Aqui añadiremos los objetos de nuestra escena desde el inspector. void Start () { Vector2 C = new Vector2(B.position.x, A.position.y); //C es la posicion X del objeto2 y la posicion Y del objeto 1 float h = (A.position - B.position).magnitude; //Distancia de hipotenusa float ca = (new Vector2(A.position.x, A.position.y) - C).magnitude; //distancia cateto adyacente float co = (new Vector2(B.position.x, B.position.y) - C).magnitude; //distancia cateto opuesto. } Sacaremos ahora el coseno del triangulo, para que nos de los radianes. public Transform A, B; //Aqui añadiremos los objetos de nuestra escena desde el inspector. void Start () { Vector2 C = new Vector2(B.position.x, A.position.y); //C es la posicion X del objeto2 y la posicion Y del objeto 1 float h = (A.position - B.position).magnitude; //Distancia de hipotenusa float ca = (new Vector2(A.position.x, A.position.y) - C).magnitude; //distancia cateto adyacente float co = (new Vector2(B.position.x, B.position.y) - C).magnitude; //distancia cateto opuesto. //Sabiendo que; cos α = ca / h float a = ca / h; //Ya tenemos alfa. float rad = Mathf.Cos(a); //ahora sacamos con Mathf el coseno de alfa y lo pasamos a una variable float, que sera el valor en radianes. Debug.Log(rad); //Nos dara 0.66 } Vale ahora tenemos el valor en radianes, ahora lo pasaremos a grados. public Transform A, B; //Aqui añadiremos los objetos de nuestra escena desde el inspector. void Start () { Vector2 C = new Vector2(B.position.x, A.position.y); //C es la posicion X del objeto2 y la posicion Y del objeto 1 float h = (A.position - B.position).magnitude; //Distancia de hipotenusa float ca = (new Vector2(A.position.x, A.position.y) - C).magnitude; //distancia cateto adyacente float co = (new Vector2(B.position.x, B.position.y) - C).magnitude; //distancia cateto opuesto. //Sabiendo que; cos α = ca / h float a = ca / h; //Ya tenemos alfa. float rad = Mathf.Cos(a); //ahora sacamos con Mathf el coseno de alfa y lo pasamos a una variable float, que sera el valor en radianes. //Para pasar de radianes a grados es aplicar la regla de 3 //-> Pi / 180 = rad / X despejamos la x // y la ecuacion es-> x=180*rad/Pi float grados = (180 * rad) / Mathf.PI; Debug.Log(grados); } No os equivoqueis por que estos no son los grados que hay que rotar, estos son los a los que se encuentra el punto B respecto al punto A, os muestro una imagen para que lo comprendais. Si nuestro sprite mirase a la derecha por defecto (que es donde comienda el grado 0) entonces 37.9 grados serian los que tendria que rotar a su izquierda, pero nosotros tenemos el offset de 90 grados por que nuestro sprite mira hacia arriba. (Por eso hay que hacer un pequeño arreglo) Y ahora si por fin lo rotaremos lo necesario para que mire hacia el otro objeto. void Start () { Vector2 C = new Vector2(B.position.x, A.position.y); //C es la posicion X del objeto2 y la posicion Y del objeto 1 float h = (A.position - B.position).magnitude; //Distancia de hipotenusa float ca = (new Vector2(A.position.x, A.position.y) - C).magnitude; //distancia cateto adyacente float co = (new Vector2(B.position.x, B.position.y) - C).magnitude; //distancia cateto opuesto. //Sabiendo que; cos α = ca / h float a = ca / h; //Ya tenemos alfa. float rad = Mathf.Cos(a); //ahora sacamos con Mathf el coseno de alfa y lo pasamos a una variable float, que sera el valor en radianes. //Para pasar de radianes a grados es aplicar la regla de 3 //-> Pi / 180 = rad / X despejamos la x // y la ecuacion es-> x=180*rad/Pi float grados = (180 * rad) / Mathf.PI; float offset = 90; //Este es el offset de nuestro sprite, por que por defecto deberia de mirar a izquierda y no arriba. //Ahora ya si, lo rotamos A.Rotate(new Vector3(,,-(offset-grados))); } Recordar que el offset cambia segun si esta a izquierda o derecha de nosotros, tambien segun este arriba o abajo. Esto es un ejemplo de una de las muchas utilidades de la trigonometría en los videojuegos, esta claro que para muchos unity ya da herramientas, pero para otros no, por eso estos conceptos son necesarios saberlos. Un saludo y espero que les sirva esta pequeña explicación!
  14. 7 points
    Pongo a vuestra disposición unos cursos sobre Unity 5 (mención especial al de "Como hacer un RPG" en inglés); otros sobre Blender que van desde lo básico hasta modelar personajes y rigging; y por último programación con C# y Javascript. También añado uno sobre inteligencia artificial. Si desáis más podéis ir al foro de Stratos, que es donde puse estos cursos más otros tantos: http://www.stratos-ad.com/forums/index.php?topic=16831.msg162995#msg162995 Espero que os sean útiles. Programación - Curso C# básico - Curso C# - Curso de JavaScript desde 0 - Curso de JavaScript para principiantes - Inteligencia Artificial Diseño Grafico Blender Cursos iniciación - Curso Blender 2.6X - Curso completo Blender Cursos nivel avanzado Cursos modelado - Curso modelado de un personaje en Blender 2.68 - Curso modelado personaje 3D estilo anime - Blenderella Cursos Rigging - Curso Blender Character Rigging - Mini curso Rigging - Tutorial Ciclo caminando - Humane Rigging Cursos Texturizado - Blender for 3d printing Cursos otras técnicas - Blend & Paint - Venoms Lab! 2 - Track Match Blend Game Engines Unity Cursos iniciación - Curso en español de C# para Unity (Nivel 1) - Bloques! Tu primer juego en Unity 5 - Unity 5 from Beginners to Pro - Curso Unity 5 - Curso Unity 5.4 - Micro tutoriales Unity 5.4 - Como crear tu primer videojuego - Unity 5.1.0 Cursos especificos - Crear un juego RPG - Create a RPG - Unity 5 RPG Series – Item System - Unity 5 RPG Character Controller - Creando el juego Space Shooter 2D - Curso creación juego 2D Unity Tutoriales varios - Tutoriales Unity5 - Blender and Unity Cursos avanzados - Curso Inteligencia artificial usando una máquina de estados
  15. 7 points
    Saludos a todos. Tras muchas búsquedas sin éxito, por fin he encontrado un Joystick analógico virtual (en pantalla) para tablets y smartphones, pero que se base por fin en el uso de la nueva GUI que tiene Unity desde la 4.6.x. He tenido la oportunidad de probarlo, y tras unas leves modificaciones ya funciona para versiones 5.0 en adelante. Lo he reducido de tamaño con sólo lo necesario y lo he vuelto a empaquetar. El Package en cuestión lleva una scene de prueba que mueve una píldora por un escenario cerrado, para probar colisiones. El Joystick como tal se encuentra dentro de un panel, dentro del Canvas (como toca). Enlace: http://www.filedropper.com/uguijoystick Espero que os sirva tanto como a mí, y que le deis mucho uso!
  16. 7 points
    Buenas. Ya va siendo hora de mostrar algo de mi nuevo proyecto. Esta vez se trata de un juego de Rally en el que podremos disputar el campeonato el mundo de rally. ¿Qué hay que hacer? Pues completar cada etapa del rally en el menor tiempo posible, conseguir dinero e ir mejorando y desactivando más coches. Tengo pensado en dividir el juego en licencias (B, A, AAA), o sea, que habrá como tres niveles diferentes en el que nos hará falta tener la licencia y un coche de ese nivel para poder correr un campeonato en ese nivel. Lo único que diferencia a una y otra licencia es la potencia del coche y el dinero a ganar. Ya está en Google Play: Versión Free :https://play.google.com/store/apps/details?id=com.MantisGames.DriftandRallyFREE Versión Completa : https://play.google.com/store/apps/details?id=com.MantisGames.DriftandRally Unas capturas de varias escenas provisionales. También habrá nieve, desierto y asfalto. Todos los escenarios serán ricos en desnieveles, como debe ser.
  17. 7 points
    Buenas, les dejo un enlace a un libro PDF sobre tips y demás, para desarrollar los niveles de sus juegos. El titulo del libro es: How to Create a Full Playable Map from Beginning to End in 11 Days using UDK? Pero vale para todo, es decir, hos explican desde como crear la idea, hasta el desarrollo completo del nivel, eso sí, está en inglés. http://www.worldofleveldesign.com/ Animense a mirarlo por que es muy completo y además es GRATISSS!!! XD poco más que añadir...
  18. 6 points
    En la anterior entrada hablé sobre trigonometría, repasando las razones trigonométricas y viendo el teorema de pitágoras. Si no lo recuerdas o has llegado nuevo aquí, míralo antes de continuar (enlace debajo). Trigonometría Vectores Matrices Funciones Introducción Si estás familiarizado con motores de videojuegos como Unity, conocerás el concepto de vector ya que se usa habitualmente. Pero ¿qué es realmente un Vector? Un vector básicamente es una flecha que apunta en una dirección y que tiene una longitud concreta: Esto sería un ejemplo de un vector y cualquier flecha apuntando en cualquier dirección sería otro ejemplo. Pero ¿cómo representamos esto? Para poder hacerlo tenemos que llevarnos nuestro vector a un sistema de coordenadas (x e y) y establecer el origen del vector en el centro del sistema. Por si no recuerdas que era un sistema de coordenadas, es una forma de visualizar un punto en el espacio. En este caso el espacio es 2D por lo que se representa con dos líneas, una horizontal (representado por el valor X) y otra vertical (representado por el valor Y) que se cruzan en un punto, llamado centro: Así quedaría nuestro vector anterior dentro de un espacio de coordenadas. Esto, por ejemplo, podría representar el movimiento de una nave en su proceso de despegue. Comienza en la posición (0,0) y sigue en la dirección del vector hasta llegar a su objetivo. Teniendo en cuenta que X es el valor horizontal e Y el valor vertical, el vector sería (2,1) Pero ¿qué podemos hacer con esto? Como has visto puedes representar movimientos con ellos, por ejemplo. Pero para ver de forma práctica su uso vamos a usar Unity3D. Cualquier versión te servirá para este propósito puesto que solo vamos a tocar código básico. En mi caso usaré la versión 2020.1. Si usas otro motor la teoría sigue siendo válida pero tendrás que buscar la forma de adaptarlo por tu cuenta. Unity internamente usa vectores para colocar un objeto dentro de la escena (realmente esto es incorrecto ya que usa una matriz, pero no nos adelantemos). Si vas al componente Transform (crea un gameobject nuevo si no tienes ninguno) te encontrarás con este Vector3 (un estructura propia de Unity) que contiene 3 valores: Estos son la posición en X,Y,Z. Pero ¿pero qué son estos valores? Pues al igual que la gráfica anterior nos indican que desde el centro del mundo hasta la posición de este objeto el vector es (0,0,0). Vamos a ver qué podemos hacer con esto. Para ello creamos un objeto de nombre Player y otro de nombre Target. Los colocamos en diferente posición y le asignamos diferentes iconos para poder diferenciarlos: Recuerda que puedes cambiar el icono en la siguiente pestaña: Una vez hecho esto vamos a crear un nuevo script de nombre Player y lo vamos a añadir al objecto Player. En este script vamos a añadir una variable Transform pública de nombre target y vamos arrastrar nuestro Target a través del inspector. Con esto tendremos acceso al vector de posición del Target desde nuestro Player. Ya tenemos acceso a los dos vectores de posición, el del personaje y el del objetivo. Sabiendo esto ¿cómo hacemos que el personaje se mueva hacia el objetivo usando vectores? Pues aquí llega la parte interesante ya que si restas el vector de posición del objetivo con el vector de posición del personaje, el resultado es el vector necesario para llevar el player al objetivo. Veámoslo gráficamente creando la siguiente función: Si pulsamos play al añadir este código, veremos cómo el personaje se mueve hasta la posición del objetivo. Vale parece que se mueve, pero quiero más. ¿Que tal si medimos la distancia que hay entre uno y otro antes de moverlo? Para esto vamos a recordar la trigonometría que aprendimos en la parte anterior. Magnitud La magnitud de un vector es la distancia que hay entre dos puntos. En nuestro caso sería la posición del personaje y nuestro objetivo. Para calcularla solo tenemos que aplicar la fórmula de la distancia. Esta fórmula es simplemente el teorema de pitágoras disfrazado, y lo vamos a ver en la siguiente imagen: Como puedes ver, nosotros lo que queremos calcular es la distancia (h) por lo que podemos convertirlo en un triángulo añadiendo X e Y. Ahora solo tenemos que usar pitágoras para despejar h. ¿Lo recuerdas? Vamos a resolverlo en código. Para ello vamos a crear una clase estática nueva llamada BasicMath donde vamos a ir añadiendo nuestras funciones matemáticas a partir de ahora. Seguiremos usando Mathf (Unity) o Math (System) para realizar las operaciones básicas que se salen del objetivo de este tutorial. Mencionar que todos los cálculos e igualdades que haremos aquí serán basados en 2 dimensiones. Una vez se han entendido correctamente los cálculos, solo hay añadir la componente z. Esta sería nuestra implementación del teorema de pitágoras. Para ver la distancia simplemente podemos añadir un log en nuestra función MoveToTarget: Si estás familiarizado con Unity ya sabrás que por defecto nos soluciona todos los problemas de vectores con su estructura Vector. Podemos acceder directamente a la magnitud de un vector desde dentro del mismo de la siguiente forma: Como puedes ver, ambos resultados son iguales, aunque nuestra implementación es menos óptima que la que usa internamente Unity. Por lo que esta clase BasicMath y todo lo que contenga es únicamente para uso educativo. La magnitud tiene un pequeño problema y es que hacer una raiz cuadrada es algo costoso a nivel computacional. Por eso habitualmente se usa el valor antes de pasar por la raiz cuadrada. Seguirás teniendo un valor que representa la distancia pero será más eficiente. Podemos crear esta implementación de la siguiente forma y equivale al SqrMagnitud de la clase Vector: Esto es genial, tenemos al personaje moviéndose al target y conocemos su distancia hasta él. Pero no queremos que el player avance directamente hacia el objetivo, sino que lo haga poco a poco a la velocidad que nosotros queramos. Para esto vamos a necesitar normalizar nuestro vector. Normalización Normalizar un vector es cambiar su longitud a 1, manteniendo su dirección. En nuestro caso de ejemplo, el vector “dir” que tenemos. Al cambiar su longitud a 1 podemos controlar la velocidad de movimiento mediante un valor multiplicador. ¿Cómo calculamos el vector normalizado (no confundir con el Vector normal)? Dividiendo el vector por su magnitud: Podemos implementar rápidamente esto en nuestra clase BasicMath: Podemos ver que equivale al valor normalized de la clase Vector: Una vez tenemos el valor normalizado, podemos multiplicarlo por un valor y hacer que el personaje se mueva en función del tiempo: Vamos a tener que pasar nuestra normalización a Vector3 ya que estamos trabajando en dos dimensiones y la posición añade la Z (aunque como este caso sea 0). Si modificamos el valor speed podremos hacer que el personaje cambie su velocidad al moverse a través del vector. Antes de continuar me gustaría darte otra forma de mover un vector de un punto a otro. Pero en lugar de basado en la velocidad, basado en un valor comprendido entre 0 y 1. Cuando el personaje está en su posición inicial, el valor es 0 y cuando llega a su objetivo es 1. Esto es llamado interpolación (Lerp). Interpolación Para interpolar un vector simplemente vamos a sumarle al vector inicial, el vector de dirección al objetivo por un valor t (comprendido en 0 y 1). Veámoslo en código: La primera línea limita la t entre 0 y 1. La segunda simplemente suma al vector de origen, el vector dirección multiplicado por t. Si la t es cero devolverá el valor “a” y si es 1 devolverá el valor “b”. Con el siguiente código podremos probar esta funcionalidad nueva: Tenemos que crear un valor t (el atributo Range nos ayudará a limitarlo entre 0 y 1) y un Vector3 que guarde la posición inicial. Esto es necesario porque si le pasamos la posición actual al Lerp los resultados se irán actualizando al ir moviéndose y el resultado no será el que buscamos. Comentamos la anterior MoveToTarget y añadimos la nueva en la función Update. De esta forma si pulsamos Play tendremos un valor t en el inspector que si vamos moviendo entre 0 y 1 hará que nuestro player se desplace más o menos cerca del target. Hay otros tipos de interpolación que veremos en el apartado de Funciones en próximas partes de este tutorial. Una vez tenemos esto, vamos a pasar con una de las operaciones con vectores más importante. Producto Escalar El producto escalar (dot) es una operación entre dos vectores que nos devuelve un valor. Este valor nos da información muy útil sobre estos dos vectores: Si este valor es cero: el ángulo entre los dos vectores es 90 grados por lo que son totalmente perpendiculares. Si este valor es negativo: el ángulo es mayor a 90 grados. Cuanto menor sea este valor, mayor será el ángulo. Si este valor es positivo: el ángulo es menor que 90 grados. Cuanto mayor sea este valor menor será el ángulo. Aquí puedes experimentar visualmente con estos conceptos: https://www.fisicalab.com/apartado/producto-escalar La fórmula del producto escalar, siendo “a” y “b” dos vectores, es la siguiente: dot = ax * bx + ay * by Ya conocido el concepto vamos a practicar con él. Primero lo añadimos la función a nuestro BasicMath. Ahora añadimos la función Dot de testeo con lo siguiente: Esto calculará el producto escalar entre el vector del personaje y el vector de dirección. Como ves hemos utilizado el transform.up en lugar de la posición. Este valor indica la dirección del vector hacia arriba teniendo como referencia el tranform. Ya conocerás estos vectores si estás habituado a trabajar con Unity. Podemos verlos mejor aquí: Si usamos estos vectores a la hora de calcular el producto escalar, los resultados serán en función a la dirección y no en función de la posición. El vector de posición no nos indica hacia donde está apuntando, sino su posición con respecto al centro del mundo. Una posición por ejemplo de (3,4,0) no nos es útil para calcular el producto escalar, sin embargo el vector.up (0,1,0) sí, ya que es una dirección en este caso hacia arriba. También hemos normalizado los dos vectores antes del dot para que sea más fácil trabajar con el resultado. Activamos esta función en Update, comentando lo demás (puedes dejar el MoveToTarget si quieres). Si damos Play podemos ir moviendo el target y ver como va cambiando el producto escalar. Pero ¿de qué sirve conocer este valor?. Pues anteriormente vimos que este valor nos da información muy relacionada con los ángulos. De hecho podemos calcular el ángulo entre dos vectores conociendo los productos escalares. Ángulo Para calcular el ángulo tenemos la siguiente fórmula,siendo “a” y “b” vectores: θ = arcocoseno (dot(a, b)) Vamos a añadir esto a nuestro BasicMath. Este resultado estará en radianes por lo que crearemos dos funciones, una en radianes y otra que convierta el resultado a grados. Hemos normalizado ambos vectores antes de hacer el Dot. De esta forma lo hará desde dentro y podremos pasarle el vector sin normalizar. El valor Rad2Deg es el factor de conversión de radianes a grados que es 180 . Esto es un valor constante: No es necesario que añadas tanta precisión, puedes coger los decimales que quieras para este fin. Creamos ahora nuestra función Angle en el Player (puedes sustituir la función Dot ya que no la volveremos a usar). Volvemos a usar el Vector.up y añadimos la función al Update para verla. Para visualizar mejor el ángulo, voy a añadir en el OnDrawGizmos el siguiente código. Esto crea dos líneas que simular el comportamiento de los vectores. Si damos al play podremos ver dos líneas que forman un triangulo, el angulo entre las dos es el que nos está mostrando por consola: Con este valor de ángulos podrías, por ejemplo, rotar al personaje para que siempre mire al target con la función transform.Rotate. Con esto llegamos al final de esta entrada sobre vectores. Ha sido algo básico pero que sirve como punto de partida si quieres profundizar por ti mismo. Como he comentado estos cálculos son teniendo en cuenta solo 2 dimensiones. Te animo a que realices los cálculos añadiendo a las fórmulas una dimensión más. Podéis encontrar el código del proyecto aquí Recuerdo que no soy matemático y que los cálculos que aquí he realizado pueden contener errores o no ser del todo precisos. Cualquier duda o anotación siéntete libre de contactar conmigo. Nos vemos en la siguiente entrada.
  19. 6 points
    Hola. estoy terminando uno de mis proyectos. se trata de un juego de naves, un matamarcianos (shoot'em up)... con toques de rouge lite. Falta terminar los modos de juego extras (modo arena, modo survival, y modo bossRush). El modo historia esta acabado, con 25 escenarios y 10 escenas especiales.... no es necesario pasar por todas para llegar al final, puedes elegir multiples caminos. (no es lineal). De momento tiene mas de 30 enemigos diferentes (contando los bosses). 16 skills diferentes (armas secundarias) y multiples mejoras para la nave. Banda sonora original con mas de 40 temas. A ver que os parece... vuestros comentarios seran bien recibidos. trailer gameplay: special scenes trailer: boss trailer:
  20. 6 points
    Estoy leyendo el libro "Unity Game Optimization" que está en Packt y la tercera edición es de noviembre de 2019. He hecho un resumen de los apartados dedicados a scripting que me parecen muy buenos. Algunos los conoceréis, otros no y otros es posible que no supiérais porqué utilizar una manera u otra. En todos los casos el concepto de optimización ve sus frutos cuando es un desarrollo de cierto tamaño. Desde mi punto de vista, si empiezas con buenos hábitos, luego no tendrás los mismos problemas de rendimiento que el resto de desarrolladores. La optimización se debe realizar desde el día 1. Paso a relatar. Optimización 1 Eliminar las callbacks vacías de Start() y Update() al crear un script si no son necesarias. El tenerlas afectará a la inicialización de la scene y al instanciar prefabs. La de OnGUI() es especialmente problemática ya que puede llamarse más de una vez por frame. En la de Update() se realiza un Native-Managed Bridge, o sea, hay que enlazar el modo managed de C# con el del código nativo dependiente de plataforma. En general no dejar nunca una callback vacía. Optimización 2 Cómo obtener los componentes de un GameObject. Hay tres maneras de hacerlo, aunque a la práctica se utilizan dos de ellas. Los datos hablan por si mismos para 30.000 objetos. // 6413 ms test = (TestComponent)GetComponent("TestComponent"); // 89 ms test = GetComponent<TestComponent>(); // 95 ms test = (TestComponent)GetComponent(typeof(TestComponent)); El mejor es del uso del template o tipo genérico. Como en C++ ;) Optimización 3 Cachear los GetComponent, preferiblemente en el Awake. Esto es realmente crítico si se realiza en el Update. Al final obtendremos un mejor rendimiento a cambio de un coste de memoria mínimo (entre 32 ó 64 bytes por item dependiendo de la plataforma). Optimización 4 El uso de funciones dentro de Update. Si las acciones no requieren se llamadas en cada frame es mucho mejor convertirlo a un InvokeRepeating que puede llamarse en el Start y cancelarse en el OnDestroy: private void Start() { InvokeRepeating("ProcessAI", 0f, _aiProcessDelay); } Optimización 5 La comparación de objetos null. La llamada directa de "gameobject == null" genera una conversión Native-Managed Bridge con la consiguiente sobrecarga. Es mucho mejor utilizar el ReferenceEquals que no utiliza la conversión. Por eso se incluyó en Unity: if (!System.Object.ReferenceEquals(gameObject, null)) { // No es null } Optimización 6 La comprobación con Tag directa genera memoria adicional y hará actuar al GC posteriormente. Utilizar el CompareTag no utiliza memoria ya que evita el Native-Managed Bridge completamente y tarda la mitad de tiempo: // Asignación de memoria y GC. Tarda el doble de tiempo if (gameObject.tag == "Player") { // realizar acción } // Evita el Native-Managed Bridge totalmente. No asigna memoria adicional if (gameObject.CompareTag ("Player")) { // realizar acción } Optimización 7 Dictionary vs List. Las List son mejores para iteraciones. Los Dictionary son mejores para búsquedas aleatorias. El Dictionary es peor para las iteraciones debido a que debe realizar una comparación hash para cada uno de los elementos. De todos modos tener los dos tipos en algunas situaciones no es mala idea. Optimización 8 La Transform. Cuando instanciamos un nuevo GameObject con GameObject.Instantiate(), uno de sus argumentos es el componente de la Transform del parent que queremos asignar, que por defecto es null y colocará el GameObject en el root. Todas las Transforms que está a nivel root necesitar crear un buffer de memoria para poder almacenar los children que tienen más aquellos que vendrán después. Esto no ocurre con las Transforms que son child. Pero si una Transform en root le cambiamos el parent una vez creada y la reasignamos, se procederá a descartar el buffer de memoria que iniciamos en el Instantiate. Para evitar esto es mejor proveer del parent en la función. Otro apartado interesante es que, hay una propiedad en la Transform llamada hierarchyCapacity. Si somos capaces de estimar el número de Transform child de este objeto root, podremos reducir el número de asignaciones de memoria. Optimización 9 World Position, World Rotation, World Scale. Cuánto más profundo esté en la jerarquía un objeto mayores cálculos son necesarios para determinar el resultado final de su estado. Esto significa que es mucho más eficiente utilizar los elementos de Local que de World. Optimización 10 Cambios en la Transform. Si es posible, agrupar todos los cambios en una Transform y no realizarlos hasta el final de todos los cálculos y en FixedUpdate. Esto evitará movimientos extraños o teleportaciones de los objetos debido a que Unity lanza eventos internos cada vez que una Transform es modificada. private bool _positionChanged; private Vector3 _newPosition; public void SetPosition(Vector3 position) { _newPosition = position; _positionChanged = true; } private void FixedUpdate() { if (_positionChanged) { transform.position = _newPosition; _positionChanged = false; } } Optimización 11 SendMessage y Find. El método SendMessage() y la familia de métodos GameObject.Find() so especialmente costosos y deben evitarse en su totalidad. El método SendMessage() es como 2,000 veces más lento que una simple llamada a una función, y el coste de Find() se escala pobremente según la complejidad de la scene aumente ya que tiene que iterar por todos los GameObject de la misma. Optimización 12 No solamente Occlusion Culling/Frustum Culling. Para los objetos que solamente tienen renderizado es factible utilizarlas únicamente. Otros objetos que utilicen cálculos internos de manera constante continuarán consumiendo a pesar del Culling. Una buena solución a este problema es utilizar las callbacks OnBecameVisible() y OnBecameInvisible(). Como los nombres dicen, estas callbacks son invocadas cuando un objeto renderizado se ha vuelto visible a una cámara o invisible respecto a todas las cámaras de la scene. Además, cuando hay múltiples cámara en la scene (por ejemplo en un juego multiplayer) las callbacks son solamente invocadas cuando es visible para una cámara o invisible para todas ellas de igual modo. Esto significa que las callback serán llamadas en el momento preciso que se necesitan. Si nadie puede ver el objeto se llamará a OnBecameInvisible(), si como mínimo un player puede verlo se llamará a OnBecameVisible(). Optimización 13 Distance vs sqrMagnitude. El cálculo de raíces cuadradas para las CPU implica bastante proceso comparado con otras instrucciones. Cuando tengamos que utilizar un cálculo de distancia, y si no requerimos de una precisión extrema, es mejor utilizar sqrMagnitude y valor a comparar por su potencia de 2. // Utilizar la raíz cuadrada en Distance() float distance = (transform.position – other.transform.position).Distance(); if (distance < targetDistance) { // dentro de distancia } // No realiza el proceso anterior float distanceSqrd = (transform.position – other.transform.position).sqrMagnitude; if (distanceSqrd < (targetDistance * targetDistance)) { // dentro de distancia } Optimización 14 Datos de Prefab a un Scriptable Object. Si tenemos muchos diferentes tipos de Prefabs que contienen datos que pueden compartirse entre ellos, como fuerza, velocidad, puntos, etc. entonces todos estos datos serán serializados en cada Prefab que luego se instancie. Una mejor solución es serializar estos datos en un ScriptableObject. Esto reduce la cantidad de datos a serializar en el Prefab, el tiempo de deserialización y el tamaño del Prefab en sí mismo reduciendo el tiempo de acciones que serán repetitivas. Optimización 15 Update(). Una mejor solución al problema del Update() es no utilizar nunca, o mejor dicho, una sola vez. Cuando Unity llama al callback Update(), o cualquiera relacionado, cruza la ya comentada frontera del Native-Managed Bridge que es una tarea costosa en términos relativos. En otras palabras, el coste de procesamiento de 1.000 Update() independiente será mucho más costoso que la ejecución de un Update() con 1.000 funciones. Para poder minimizar este problema es mejor agrupar todos los Update() en un solo Update() global que luego llame a las diferentes funciones que requieran la acción.
  21. 6 points
    Hola, He creado unos pocos vídeos de programación básica de NPC's, o programación de NPC's básicos. La intención es ir creando mas de esta tématica, sin obligación, y de tanto en tanto, pero irlos agrupando en la misma lista de visualización de youtube: Aquí os la dejo: Por ahora hay tres vídeos, o 2.5 por que el último es un poco ampliación del primero. -Como crear NPC's en Unity que te siguen. -Creamos un centinela con Waypoints en Unity, -Como hacer un NC persiga y huya en modo pánico. Ya ire informando de nuevas incorporaciones a la lista 🙂
  22. 6 points
    Introducción En esta ocasión vamos a crear una Carta con un efecto 3D similar a la que vemos en el gif anterior. Para ello vamos a partir de un proyecto donde tenemos preparados los assets necesarios. Este proyecto podemos descargarlo desde aquí: URL: https://drive.google.com/open?id=19J6lgCA-DH28lMu9dmntk1K5l3lPE66f Una vez descargado vamos a abrirlo desde el Unity Hub. Este proyecto está creado con la versión 2019.2.9f1 asique podría ser incompatible con versiones anteriores. Una vez abierto vamos a tener una escena llamada “Sample Scene” y una serie de carpetas con los modelos,sprites,prefabs… necesarios. Además contamos con los paquetes TextMeshPro y PostProcessing que usaremos a lo largo del tutorial. Puedes acceder en todo momento a los paquetes usados a través del Package Manager. Preparando el proyecto En primer lugar vamos a abrir la escena “Sample Scene” y vamos a arrastrar en ella el prefab “Hornet” dentro a la ventana de Hierarchy. Verás que aparece en rosa, eso es debido a que no tenemos aún ajustado el Render Pipeline. Vamos a empezar por ahí. Vamos a crear una carpeta Settings donde colocaremos aquellos ajustes globales del proyecto. Siéntete libre de elegir otro nombre, yo siempre soy malisimo poniéndolos. Una vez creada vamos crear una configuración pulsando click derecho y Create/Rendering/LightweightRenderPipeline/PipelineAsets. Elige el nombre que quieras y seleccionalo para verlo en la ventana de Inspector. Aquí tenemos los ajustes del Render Pipeline. La configuración es muy intuitiva y prácticamente todo hace lo que indica. En nuestro caso solamente vamos a activar el HDR y el antialiasing. Lo demás no lo tocaremos, aunque esto va de experimentar, así que “rómpelo” a tu gusto. Una vez creado vamos a añadirlo a nuestro proyecto, para ello vamos a irnos a ProjectSettings/Graphics y lo colocamos en el hueco de Scriptable Render Pipeline Settings. Hecho esto si volvemos a la escena podemos ver que el color rosa ha desaparecido. Aunque ahora se verán blanco. No te preocupes que ese será nuestro siguiente paso. También verás que hay una luz añadida dentro del prefab de Hornet. Está configurada por mi pero llegado el punto puedes quitarla o cambiarla como quieras. Creación de Shaders Vamos a darle color a nuestros objetos ahora. Como has podido ver todos los objetos están en blanco. Eso es porque nuestros shaders y materiales están por defecto. Para nuestro objetivo vamos a necesitar crear un shader con la herramienta Shader Graph. Esta ya viene por defecto en todos los proyectos que usen el Scriptable Render Pipeline nuevo. Para ello vamos a crear una nueva carpeta llamada Shaders y vamos a crear un nuevo Shader PBR (Create/Shader/PBR Graph). Puedes ponerle el nombre que quieras, en mi caso lo he llamado Standard_SG (ya he dicho que soy muy malo poniendo nombres). Vamos a seleccionarlo y abrirlo. No es el objetivo de este taller aprender a usar ShaderGraph, asique no voy a pararme en explicar el contenido, aunque como veréis es muy fácil e intuitivo lo que haremos. Crearemos las siguientes variables: Conectaremos al Albedo un Sampler de una textura y la multiplicaremos por un color. Cómo veis el shader es lo más simple posible. Haremos lo mismo en el canal de Emission para poder ajustar la emisión de algunos objetos posteriormente. Pulsamos en Save arriba a la izquierda y cerramos. Ya tenemos nuestro shader creado pero tenemos un problema que veremos a continuación. Stencil Buffers Para obtener el efecto que buscamos tenemos que conocer el concepto de Stencil Buffer. Con ellos podemos principalmente renderizar unas partes de un objeto y descartar otras. Aquí podemos obtener más información: https://docs.unity3d.com/Manual/SL-Stencil.html https://www.ronja-tutorials.com/2018/08/18/stencil-buffers.html El objetivo es mantener “invisible” un objeto y que cuando este se encuentre en la “visión” de otro objeto, se muestre. Vamos a necesitar por dos shaders: Uno que leerá del stencil buffer y se dibujará solo donde el búfer tenga un valor específico, en cualquier otro lugar se descartará. Por otro, un shader que permanerá siempre invisible y que solamente mostrará aquellos valores específicos que coincidan con el stencil buffer. Para el primer solo necesitamos añadir unas líneas, pero actualmente no es posible hacerlo a través del ShaderGraph. Por lo que vamos a realizar una transcripción del Shader Graph al código. Para esto vamos crear un nuevo Shader Unlit pero esta vez no será de ShaderGraph. Le ponemos de nombre Standard_StencilRead por ejemplo y lo abrimos. Mientras se abre vamos a volver al Shader Graph y vamos a realizar la copia del código del shader. Para ello nos vamos al PBR Master Node y con el botón derecho seleccionamos Copy Shader. Una vez copiado vamos a pegarlo en nuestro reciente nuevo shader unlit creado, sobreescribiendo todo lo que este tuviese. También deberás cambiar la primera línea y ponerle tu la dirección y el nombre que elegimos antes. En mi caso lo he guardado en MyShaders con el nombre Standard_StencilRead. Ahora tenemos el mismo shader de Shader Graph pero en código para poder modificarlo. Vamos a necesitar añadir una nueva propiedad que será el valor específico del stencil. Simplemente dentro de properties al final, debajo del Color añadimos lo siguiente: [IntRange] _Stencil ("Stencil Value", Range(0,255))= 0 Quedando de la siguiente manera: Por último vamos a necesitar añadir los ajustes del Stencil debajo de los Tags antes de los diferentes pases. Esto hará que sólo cuando tengamos el valor de referencia, el objeto se muestre. Podemos obtener más información sobre la sintaxis y el contenido en los enlaces que anteriores. Ya podemos guardar el shader y volver a Unity. Tenemos preparado nuestro primer Shader. Para el segundo simplemente creamos otro shader unlit de nombre StencilWrite por ejemplo. Este estará siempre invisible y servirá para mostrar los objetos que compartan valor de referencia. Abrimos el shader y lo modificamos de la siguiente forma: En properties añadimos el valor de Stencil como con el anterior y eliminamos cualquier otra propiedad (normalmente textura) ya que este shader queremos que se muestre totalmente invisible. Añadimos el Stencil y le decimos que esté siempre comparando y si en algún momento el valor de referencia es el mismo, lo reemplace. Ahora le decimos al buffer de profundidad que no se escriba (por ser un objeto que será invisible) y cambiamos el modo de Blend. Podemos obtener más y mejor información de esto aquí: https://docs.unity3d.com/Manual/SL-Blend.html También eliminamos todos los añadidos de Fogs por defecto de Unity y aquellas referencias a texturas que no nos interesan. Por último hacemos que la función frag devuelva siempre 0, ya que como hemos comentado esto se muestra siempre como invisible. Con esto tenemos todo listo para pasar al montaje de la carta. PD: Asegurate también de que lo tienes en la misma ruta que el anterior. Esto no es necesario, pero te facilitará encontrarlo más adelante. En mi caso al igual que antes, esta en la ruta MyShaders. Montaje de la carta Para empezar vamos a cambiar por fin el blanco de nuestra escena, para ello vamos a irnos a Materials/Hornet y seleccionando todo vamos a elegir nuestro Shader (en este caso el Standard_StencilRead) Ahora tendremos que arrastrar las texturas requeridas (Main Texture y Emission Texture) si procede y establecer el MainColor en blanco (tened cuidado que el alfa no este a 0) y el EmissionColor en negro. En el caso que no tengamos texturas (como en el caso del personaje Hornet) simplemente cambiale el MainColor a tu gusto. Puedes hacerlo similar al original o ponerle tu propia versión. Así quedaría el del grass_material por ejemplo: O el dress_material, que no tendría textura: Sigue estas pautas en los demás materiales. El stencil value lo cambiaremos más adelante, de momento necesitamos ver en pantalla todo y no solo cuando este a través de nuestro “marco”.. Una vez terminado debería de quedarte algo similar a esto: Ahora vamos a crear un nuevo objeto en la escena llamado Card y lo ponemos en la posición 0,0,0. Ahora buscamos el Sprite “cover” dentro de Sprites y lo arrastramos dentro de Card. Le damos el tamaño a nuestro gusto. Este será el envoltorio de la carta. Ahora vamos a crear un Quad dentro de Card. Le ponemos de nombre StencilMask y lo colocamos en la posición 0,0,0 también. Este será nuestro marco a través del que se verá nuestra Hornet. Para poder ajustarlo vamos a tener que configurar ya el valor de referencia del stencil así como crear un nuevo material StencilWrite para nuestro quad recién creado. Vamos a empezar por esto último, crearemos un nuevo material con el shader StencilWrite. Lo colocamos dentro de Materials para tenerlo ordenado. A este material le vamos a poner en el valor de Stencil el valor 2 por ejemplo. Es simplemente un valor referencia, mientras tanto el receptor como el emisor tengan el mismo, funcionará. Una vez configurado vamos a arrastrarlo al StencilMask (o cambiamos el material dentro de MeshRenderer) para colocarselo. Veréis que se ha vuelto invisible, eso es que funciona como debería. Por último vamos a irnos a los materiales StencilRead que configuramos anteriormente y vamos a ponerles el mismo valor de referencia al Stencil. Seleccionamos todos o uno a uno y en Stencil Value le colocamos 2. Ahora debería de volverse todo invisible en la escena quedando solo la carta en negro. Vamos a desactivar de momento la carta llamada “cover” (o el nombre que tu le hayas puesto) de la ventana de Hierarchy. No se ve nada pero no es un error. Ahora mismo todos los shaders tienen el mismo Render Queue por lo que nuestro efecto no está funcionando. Más información de esto aquí: https://docs.unity3d.com/Manual/SL-SubShaderTags.html Sabiendo esto solamente tendremos que asegurarnos que nuestro StencilWrite se renderice antes. Vamos a nuestro material y le restamos 1 al RenderQueue. Con esto ya deberiamos tener visible nuestro modelo únicamente cuando estemos viendolo a través de nuestro quad. Ahora volvemos a activar el cover para ajustar la carta y el hueco como queramos. Al activarlo verás que tapa la visión a través del quad. No te preocupes, simplemente ve a los ajustes del SpriteRenderer del cover y cambia el MaskInteraction a Visible Outside Mask. Ahora ajustamos el Quad hasta tener el tamaño que deseemos. Una vez confirmado podemos probar a girar en la escena alrededor de la carta para comprobar el efecto. Para organizar mejor la escena vamos a colocar el objeto Hornet dentro de Card y vamos a crear un prefab para tenerlo guardado. Gracias a los Nested Prefab ya podemos hacer prefabs dentro de prefabs, asique nos viene genial. Ahora solo nos falta añadirle algo de texto. Vamos a usar TextMeshPro para esto. Pulsamos botón derecho y creamos un nuevo texto en 3D. Vamos a empezar por el nombre de la carta, por lo que le ponemos de nombre al text “Name” por ejemplo. Vamos a escribir el texto del nombre en el apartado Text y vamos mover y escalar el objeto colocándolo donde más nos guste. En mi caso he decidido ponerlo arriba. Vereis que no se ve cuando lo colocamos en la zona de la carta. Eso es por el orden de renderizado que tienen. Vamos a abrir los ajustes extra del texto (extra settings) y vamos a subirle el orden in layer a 1. Con esto conseguimos verlo, pero existe un problema, que el texto aparece también por detrás. Esto lo solucionaremos más adelante ya que tendremos que añadir un script simple para que active el culling. Llegados a este punto me he dado cuenta de que la carta está colocada del revés y el nombre por la parte trasera se ve invertido. En nuestro caso podemos solucionarlo rápido ya por delante la carta no se ve afectada. Simplemente nos vamos al objeto “cover” y marcamos Flip X. De esta forma la parte de atrás estará perfecta. En el caso de que tuvieras una imagen diferente deberías tener cuidado ya que la carta es la misma tanto en la partal como en la dorsal. Todo se dará la vuelta. Si quieres tener un control más exacto, deberás tener una carta delantera y otra trasera, cada una con su ajustes (y quizás optimizada para no pintar dos cada cara). Vamos a guardar el avance, aplicamos el prefab y guardamos escena. Deberíamos tener algo similar en estos momentos: Vamos a crear ahora otro texto para colocarlo en la parte de debajo. Duplicamos el objeto Name con Control+D y cambiamos el nombre a Description. Movemos el objeto a nuestro gusto, en mi caso lo coloque en la parte de abajo, centrado. Puedes tocar los ajustes del TextMesh que son maravillosos, sobre todo si has trabajado con el deprecado Text. Si queremos podemos cambiar la fuente. Para ello simplemente tendrás que descargarla de internet (o obtenerla de otra forma) y meterla dentro de Unity. Una vez dentro no es simplemente arrastrarla. Para poder usarla en TextMesh necesitarás crear un atlas de la fuente. Pero es fácil de hacer, simplemente abre la ventana Font Asset Creator desde WIndows/TextMeshPro. Selecciona la fuente y pulsa Generate Font Atlas (si quieres cambiar algún otro ajuste puedes hacerlo, pero ten cuidado. Más información sobre esto aquí: http://digitalnativestudios.com/textmeshpro/docs/font/ ) Una vez generada simplemente guárdala donde quieras y luego colócala en el texto dentro de Main Settings: Una vez tengamos la descripción vamos a guardar el prefab y a colocar los Post Procesos. Para ello Vamos a ir a la cámara y vamos a asegurarnos que tiene añadido un Post Process Layer. Esto es imprescindible para poder continuar. También vamos a activar a antialiasing FXAA y vamos a crear un nuevo layer PostProcessing para posteriormente usarlo en el Volume. Ahora vamos a crear un nuevo objeto en la escena. Le vamos a añadir el componente Post Process Volume. Vamos a marcar IsGlobal porque solo tendremos este para toda la escena y vamos a seleccionar un profile. En nuestro caso no tenemos ninguno creado, asique le daremos a New. Ahora simplemente asegurate de que este objeto está en el Layer PostProcessing De otra forma no funcionará y no podremos ver ningún cambio. Una vez configurado podremos ir añadiendo efectos ya creados por Unity o crear los nuestros propios. En este caso vamos a usar dos creados, el Bloom y el Color Grading. Pulsamos en Add Effect y seleccionamos uno y después el otro. Aquí puedes sacar tu lado artístico y elegir la configuración que más te guste. En mi caso después de una serie de pruebas quedó así: En este punto deberías tener algo similar a esto. Si no es así asegúrate de que el material del lazo tiene un emission color bien configurado. Por último nos queda solucionar el error del texto por ambas caras. Para eso simplemente vamos a crear un script con el nombre CullingTextMeshPro o el que querais y vamos a dejar solo la función Awake con el siguiente código: De esta forma al darle al Play el texto automáticamente hará culling y no se renderiza por detrás. Estuve informándome sobre otras formas de hacer esto, pero las respuesta de Unity fueron que esta era la forma. Pero si conocéis otra forma contactad conmigo y lo actualizo. Espero que os haya gustado y hayáis aprendido cosas nuevas que al final es el objetivo esto. Cualquier duda contacta conmigo via twitter: https://twitter.com/_davidlopez29 o por aquí Hasta pronto!
  23. 6 points
    Hola soy James Roman, tengo ya varios años trabajando con Unity, y actualmente trabajo en una compañía como desarrollador de experiencias en Realidad Virtual. Y tengo ya bastante tiempo trabajando en VRLAB. Puedes verlo desde aqui. ¿Que es VRLAB? Es básicamente una colección de componentes para interacciones en VR usando Oculus, me he enfocado bastante en las armas ya que creo que es una de las cosas mas divertidas de probar en la Realidad Virtual, he incluido diferentes tipos de armas, escopetas, armas automáticas, revolver, arco y flecha, espadas. También diferentes tipos de recarga para estas armas, puedes cambiar manualmente el cargador a cada arma cuando este se agote, recargar usando diferentes tipos de gestos como en dead and buried, puedes recargar el revolver haciendo un giro rápido con la mano. - Armas - Como ya he mencionado he trabajado bastante el tema de las armas con un completo sistema de armas, varias armas ya incluidas (Escopetas, revolver, Automáticas), puedes tomar las armas existentes como base para crear las tuyas, o crear nuevas armas desde 0. - Completo Sistema de Interacción - También posee un completo sistema de interacción, muy extensible, puedes tomar objetos, interactuar con objetos, mover palancas, botones etc, crear animaciones de interacción diferentes para cada objeto, y diferentes comportamientos incluso para cada mano. - Arco y Flecha - Posee un arco realista con el cual puedes lanzar flechas, puedes tomar una flecha de tu espalda o simplemente tomar una que ya hayas lanzado, estas se pegan a los demás objetos de una manera bastante realista. - Diferentes Modos de Recarga - Posee diferentes formas para poder recargar las armas, puedes cambiar el cargador una vez que este se haya acabado, o simplemente realizar gestos con la mano como en dead and buried para recargar tus armas o simplemente tener munición infinita. - Sistema de Combate Cuerpo - En VRLAB puedes tomar un par de espadas y luchar contra los enemigos, los cuales responderán correctamente a las físicas, ademas de eso puedes golpear a los enemigos con tus armas, como con el arco o una escopeta si no tienes munición. - Botones y Palancas - Botones y palancas que responden correctamente a las físicas, desde las distancia puedes activar una palanca con un disparo o simplemente lanzando un objeto. - AI - Aunque el fuerte de este asset no esta en la AI, he añadido unos ejemplos bastantes interesantes y extensibles para trabajar con estos mismos. - Character Controller y Teleport - Tienes diferentes formas de moverte en VRLAB, la mas común quizás moviéndote alrededor con el joystick o usando un sistema de teleport muy parecido al de roborecall. Todo esto en prefabs bien organizados listos para tomar y soltar en la escena, con montones de posibilidades de modificación mediante el inspector, de igual manera me he esforzado para crear un código legible y placentero a la vista, así que si quieres simplemente entrar y mirar como esta hecho todo, y aplicar tus propias modificaciones mediante código, no debería ser muy difícil para alguien que tenga ya su experiencia con Unity. - Futuras Actualizaciones - - Añadir nuevas armas, entre ellas un lanzacohetes. - Sistema de inventario, para que puedas cargar varios objetos a la vez. - También cabe destacar que me gusta roborecall, y quizás añada algunas de sus funciones, entre ellas la posibilidad de tomar balas en el aire y devolverlas a los enemigos. - Luego simplemente escucharlos a ustedes y seguir mejorando. Dejo nuevamente el link al assetstore aqui, si lo pruebas no dudes en dejar un review para seguir mejorando, y si quieres contactar conmigo directamente puedes escribirme a james@unity3dninja.com finalmente los dejo con algunos vídeos cortos mostrando distintas funcionalidades.
  24. 6 points
    Lamentum Se cuenta que un conde vive en una mansión oscura. De él se dice que puede conceder cualquier deseo y que es tal su poder que incluso la muerte no se atreve a cruzar sus dominios. Pero todo tiene un precio... ¿Te atreverías a pagarlo? Sobre el juego: Lamentum es un juego survival-horror en estilo pixel art que tiene lugar en Nueva Inglaterra a mediados del siglo XIX. Tomarás el papel de Victor, un joven aristócrata que busca desesperadamente la cura para una rara enfermedad. El juego se basa en la exploración y resolución de enigmas, pero sin olvidar la acción y el combate. Acerca de nosotros: Somos un pequeño equipo de dos personas con base en Madrid y Sevilla. Aunque tenemos experiencia en el sector de los videojuegos, este es nuestro primer proyecto en equipo. También contamos con la colaboración de Black Light Sound, encargado de la música y los efectos sonoros. Soundcloud: https://soundcloud.com/blacklightsnd Gracias por pasaros y agradeceríamos vuestros comentarios. Podéis seguirnos en: Twitter: https://twitter.com/ObscureTales Facebook: https://www.facebook.com/ObscureTalesGames
  25. 6 points
    Hola a todos, mi nombre es David y este es el primero de una serie de tutoriales sobre Unity3D. Esta iniciativa surge del programa Unity Student Ambassador y están creados por mi inicialmente para workshops presenciales. Los he adaptado a este formato pero si tienes cualquier duda no dudes en preguntarme. Espero que os guste. Introducción ¿Que es Shader Graph? La creación de shaders en Unity ha sido tradicionalmente el terreno de juego de personas con habilidades para programar. Shader Graph abre el campo para artistas y otros miembros del equipo para que la creación de shaders sea mucho más sencilla. Solo conecta nodos en una red gráfica y podrás ver los cambios al instante. Requisitos El Shader Graph está disponible desde Unity 2018.1. Está diseñado para funcionar con otra característica de Unity 2018.1: Scriptable Render Pipeline (SRP). Por lo tanto, no puede usarlo con el Built-In Unity Renderer. Tiene por tanto soporte tanto para LWRP como para HDRP (o para su propio SRP). Para este tutorial usaré la versión 2019.2.9f1. ¡Comencemos! Lo primero que necesitamos es abrir Unity y crear un nuevo proyecto. Asegúrese de que elige usar el nuevo SRP. En nuestro caso elegiremos el LWRP. Confirmamos y esperamos que Unity lo prepare todo. Una vez dentro de Unity ya podemos ponernos a trabajar. Por defecto debería tener incluido el paquete Shader Graph. Puedes comprobar ese y otros paquetes instalados en Windows/Package Manager. Nuestro primer Shader En la ventana Project, pulsamos el botón y elegimos Create/Shader/PBR Graph. Si queréis conocer más acerca del PBR está es una buena guía: https://blog.teamtreehouse.com/beginners-guide-physically-based-rendering-unity Nombramos el archivo con el nombre que queráis. En este caso le llamaremos Standard_Color. Ya tendríamos nuestro primer Shader creado, vamos abrirlo. Lo seleccionamos y en la ventana Inspector pulsamos Open Shader Editor. Si todo ha ido bien, deberíamos ver esto: Dentro del Shader Editor podemos ver tres sectores claramente diferenciados: PBR Master Node: Es el nodo principal, al que acaban llegando todos los demás. Es el encargado de mostrar las características en el material. BlackBoard: Puedes activarlo y desactivarlo arriba a la derecha. Es donde creas y guardas las propiedades que necesitas usar. Encontrarás Colores, Vectores, Texturas etc… Estas pueden aparecer en el inspector del material para ser usadas más adelante. Preview: Es la previsualización actual de la entrada del PBR Master Node. Puedes cambiar el tipo de renderización pulsando el botón derecho. (Cubo, quad,sphere…) Una vez conocemos las partes vamos a añadirle funcionalidad a nuestro nuevo Shader. Comencemos añadiendo color. Vamos a abrir el Blackboard y vamos a pulsar en el +. Con esto podremos crear una variable de entre las que Shader Graph nos ofrece. En este caso elegiremos Color. Ahora podremos cambiarle el nombre, pero en nuestro caso lo dejaremos tal y como está, con el nombre Color, que al fin y al cabo es lo que será para nosotros. El toggle de Exposed indica si quieres que esa variable aparezca posteriormente en el material para ser editada de forma rápida. En nuestro caso así lo queremos así que la dejamos marcada. En Default puedes elegir el color que desees por defecto, como he dicho podrás cambiarlo después en el material pero si quieres ver como queda en el Shader Editor tendrás que cambiarlo aquí. Por último el Mode te permite establecer el color como HDR. Puedes hacer efectos realmente atractivos con esto pero de momento lo dejaremos como está. Una vez creado nuestro Color vamos a arrastrarlo hacia el Grid donde esta el PBR Master y lo soltamos. Como vemos este nodo Color solo tiene una salida, conectamos la salida con la entrada de Albedo. Si habías cambiado el color default verás que la Preview ahora aparece de otro color. Sino puedes ir ahora y cambiarlo. Una vez hecho esto pulsamos arriba a la izquierda en Save Asset y podemos cerrar el editor. Ahora solo nos falta ver nuestro shader en pantalla. Para esto añadimos una esfera a la escena y creamos un nuevo material. Le pondremos de nombre Standard_Color_MAT, por ejemplo. Una vez creado el material, lo seleccionamos y en el desplegable del Shader elegimos ShaderGraph/Standard_Color o como llamases a tu Shader. Arrastramos nuestro nuevo material y lo soltamos encima de la esfera y … Ahora podemos cambiar cambiar desde el Material el Color, ya que anteriormente lo activamos. Nodos importantes Antes de continuar el tutorial voy a explicar algunos de los nodos más usados ya que los vamos a usar más adelante. Me dejo muchos pero para esta introducción son suficientes: Math Basic: Son las operaciones matemáticas más comunes. Suma, División, Multiplicación, Resta … UV: Son nodos que actúan sobre las coordenadas de uv. Podemos rotarlas, moverlas y darle algunos efectos como el Twirl o Spherize. Veremos un ejemplo más adelante. Shapes: Son texturas generadas proceduralmente dentro del editor. Podemos crear círculos, rectángulos, polígonos etc… One Minus: es simplemente la operación 1 - x. Es muy útil como veremos más tarde, tanto que tiene su propio nodo. Noise: es un nodo generador de ruido. Veremos también su uso más adelante. Step: es un nodo que dado un valor entre 0 y 1, compara la entrada con ese valor y devuelve 0 si es menor y 1 si es mayor. Por ejemplo: si nuestro valor es 0.4, todos los valores por encima que entren en el nodo, serán convertidos a 1 y todos los inferiores serán 0. Dot: es un nodo que calcula el Producto Escalar entre vectores. Devuelve 1 si apuntan exactamente en la misma dirección, -1 si apuntan en direcciones completamente opuestas y 0 si los vectores son perpendiculares. Lerp: es un nodo que devuelve el resultado de la interpolación lineal entre las dos entradas en función de la entrada T. El valor de la entrada T está sujeto al rango de 0 a 1. Por ejemplo, cuando el valor de la entrada T es 0, el valor de retorno es igual al valor de la entrada A , cuando es 1, el valor de retorno es igual al valor de la entrada B y cuando es 0.5, el valor de retorno es el punto medio de la dos entradas A y B . Dissolve Shader Una vez conocemos los nodos más importantes, vamos a hacer un Shader algo más complejo que el anterior. Vamos a crear un efecto que disuelva el objeto haciendo que desaparezca y aparezca a nuestro gusto: Para esto volvemos a crear un nuevo Shader y le ponemos de nombre Dissolve. Lo abrimos y seleccionando el PBR Master pulsamos en el icono del engranaje. Aquí vamos a encontrar algunos ajustes interesantes como si el objeto es Opaco o Transparente. En este caso lo dejaremos como está (Opaque) y lo único que marcaremos será el Two Sided. Esto hará que el objeto pinte también sus caras internas, lo que conlleva eso sí, un coste extra. Tenlo en cuenta en el futuro, en este caso para el Cubo en cuestión, nos interesa que las caras internas también se vean cuando está disolviendo. Una vez marcado, vamos a crear algunas variables que usaremos. En primer lugar necesitaremos un valor comprendido entre 0 y 1 que se encargue de llevar el progreso disuelto. Será 0 cuando el objeto se vea por completo y 1 cuando esté completamente disuelto. Para eso en el BlackBoard crearemos un Vector1(que no es más que un simple número) y lo nombraremos como Dissolve Value por ejemplo. Para facilitarnos el trabajo, podemos cambiar el tipo de número con Mode. En nuestro caso está comprendido entre 0 y 1 por lo que elegiremos Slider y rellenaremos el min y el max con esos valores. A su vez, necesitaremos también un Color para el objeto, como en nuestro anterior Shader y un Color diferente para la parte que se esté disolviendo. Creamos ambas variables, estableciendo el Color para disolver cómo HDR si quieres que brille como el del gif (necesitarás también tener el paquete de post procesos y activar el Bloom). Por último necesitaremos un valor que indique el grosor que tendrá el dissolve. Podemos revisar el Gif para ver el grosor que tiene la parte que se está disolviendo. Creadas todas las variables en mi caso quedó así: Para el efecto de disolver necesitamos en primer lugar una textura que genere ruido donde las zonas negras indiquen lo que llevamos disuelto y las zonas blancas lo que nos queda por disolver. Por suerte, como vimos antes, tenemos un nodo de ruido perfecto para este uso: Simple Noise, asique lo añadimos. Podemos cambiar el valor de Scale del nodo a nuestro gusto. Cuanto menor sea el valor más “zoom” hará el ruido. También vamos a necesitar el nodo Step que si tenías dudas de su uso, en este caso lo vas a entender perfectamente. Ahora unimos la salida de Simple Noise a la entrada Edge del Step. Ahora podemos cambiar el valor del Step entre 0 y 1 para ver su utilidad real. Los valores de ruido que estén por debajo de ese valor devolverán 0 y los que estén por encima devolverán 1. Es decir cuando el Step sea 0 el objeto no se verá y cuando sea 1 se verá completamente. Justo lo que queremos que ocurra. Simplemente conectamos nuestra variable DissolveValue a la entrada In del Step. Para hacer pruebas vamos a colocar la salida del Step en el Albedo del PBR Master. Vamos a guardar y vamos a Añadir un cubo a nuestra escena. Crearemos un material con nuestro shader y se lo colocaremos al cubo. En nuestro material podremos cambiar el valor del DissolveValue. Como vemos el efecto se acerca a lo que buscamos, aunque tenemos dos problemas. Primero no se está disolviendo realmente ya que está pasando de negro a blanco simplemente. Y segundo que el efecto está al contrario, cuando el DissolveValue vale 0 debería verse el objeto completo y cuando está a 1 indica que el objeto está completamente disuelto. Vamos a volver a abrir el Shader Editor para solucionar ambas cosas. Primero vamos a hacer que la parte negra se convierta en transparente. Para ello simplemente tienes que conectar la salida del Step con el Alpha del PBR Master. También tendrás que activar el AlphaClip. Aunque el valor que entra por defecto es 1 tendrás que ponerle tu el valor a través de un nodo. Simplemente crea un nodo Integer (que es un número sin decimal) y conectalo a AlphaClip. Para el segundo problema simplemente usaremos el nodo que comentamos anteriormente. OneMinus. Si a 1 le restamos el DissolveValue obtendremos la parte contraria, que es justo lo que necesitamos. Si guardamos y probamos comprobamos nuestro material ahora podemos ver que funciona como queriamos. Se disuelve de blanco a negro con el ruido que creamos. Solo nos falta añadirle color. Para ello volvemos al editor. Necesitamos pintar el borde que se disuelve y a raíz de ahí lo que tengamos a un lado del borde lo borramos y lo demás lo pintamos del color normal. Una forma de encontrar el borde es sumar el DissolveValue y el borde y restar por un lado el Step de la suma y por otro el Step del DissolveValue solo. Es más fácil de entender con una imagen (para que sea más visual he cambiado el valor default del Dissolve Value a 0.5): Como vemos ahora tenemos el borde diferenciado, pero no lo estamos usando. Lo que vamos a hacer es pintar con los colores que creamos al principio. Una buena forma de hacerlo es usar Lerp. Podemos hacer que si la resta es 1(blanco) se coloree con el Color del Borde y si es 0(negro) el color sea el normal. Y esa salida del Lerp la conectamos a Albedo. Ahora podemos guardar y probar el shader. Si todo ha ido bien debería funcionar como esperábamos. Puedes cambiar a tu gusto los valores del material, como los colores o el borde. Si eres perfeccionista te darás cuenta de que si el borde es muy grande, pueden quedar algunos restos al disolverse. Esto podemos arreglarlo con un simple cambio. Sumando el valor del borde al dissolve antes de hacer el OneMinus. También podrías crear una variable para el Scale del Simple Noise. Así tendrías un valor más que podrías modificar desde fuera sin tener que cambiar el shader. Por último vamos a añadir una textura que se añada al color, así lo podremos usar en más objetos. Simplemente crea una variable de tipo Texture2D y arrastrala al grid con los demás nodos. Tendrás que sacar un nodo llamado Sample Texture 2D y arrastrar la textura a la entrada correspondiente. Luego solo queda multiplicar por el color normal y sustituirlo en la entrada A del Lerp anterior. Guardamos y desde el inspector del material añadimos la textura que queramos y habríamos terminado. No es la única forma de hacer este efecto, hay muchas otras, esta es la forma que yo usé. Espero que os sea útil. Cualquier duda que tengáis hacérmela saber y estaré encantado de ayudaros. Podéis encontrarme también por twitter: https://twitter.com/davidlopezdev Nos vemos en el siguiente.
  26. 6 points
    Hola de nuevo a tod@s. Después de algún tiempo sin postear nada por aquí, y tras la satisfactoria experiencia con mi anterior proyecto SpinBlock Puzzle del que ya os hable en otro hilo, os traigo lo último en lo que estoy trabajando. Un juego de estrategia táctica multijugador por turnos, con ambientación medieval fantástica. Donde la acción se reparte entre la construcción y evolución del poblado o ciudad, mediante la obtención de recursos. Y el combate contra otros jugadores en diferentes mapas disponibles, empleando las tropas y máquinas de asedio creadas con antelación o reclutando otras nuevas. Y levantando defensas para impedir el avance del contrincante. Aquel que consiga cruzar las defensas del oponente obtendrá el estandarte del adversario y ganará la partida. Pero para ello tendrá que desarrollar su estrategia en función de los recursos disponibles, la distribución del mapa, la raza de los personajes, las actualizaciones conseguidas y las habilidades desarrolladas. Próximamente os ampliaré detalles. Por ahora os dejo con algunas capturas para abrir boca. Espero que os gusten y quedo a la espera de vuestras críticas y sugerencias. Saludos. Despliegue de defensas de nivel básico Despliege de defensas de nivel intermedio Detalle de una trampa de estacas y un ariete Encendiendo la barbacoa!!!!
  27. 6 points
    EDITO: La pagina de steam ya esta activa, Delta Squad en Steam con su correspondiente trailer y demas 🙂 Ya puedes comprarlo!! Hola!!!, Llego el momento de presentar el proyecto en el que llevo varios meses currando. Se llama Delta Squad, y al igual que mi anterior trabajo FullBlast esta pensado para old gamers y gente que gusta de arcades clasicos con gameplay clasico 100%. Aqui no hay ayudas a los jugadores, ni "complicado" lore, al mas puro estilo john carmack, donde decia aquello de que la historia en un juego tal y cual... xDDelta Squad es un arcade donde tenemos que liberar a la humanidad de un maligno virus y para ello iremos cumpliendo misiones en cada nivel hasta conseguir nuestro objetivo. Se puede jugar hasta 4 personas local coop, y trae un modo para activar el "friendly fire" que es siempre tan agradecido en estos juegos (porque matar a tus compañeros siempre se agradece xD) Aqui os dejo la primera captura del proyecto 🙂 Delta Squad es un juego muy particular y que solo gustara a un porcentaje MUY pequeño de la gente. El juego va enfocado a la gente que busca un juego retro como los arcades de los 90', si no te encuentras en ese target, entonces el juego NO tiene nada que ofrecerte y no te recomiendo comprarlo porque te aburrira mucho. Si por el contrario te gusta comprar juegos asi "raros" como me pasa a mi, entonces seguramente este Delta pueda estar entre tus retro-favoritos. Para gustos colores... Edit: Aqui tenemos el primer video en movimiento del juego 🙂 Gameplay video
  28. 6 points
    Buenas Os presento el proyecto que estoy llevando a cabo yo solo desde hace 1 año. Vendí mi antiguo negocio hace unos meses y estoy trabajando en esto a tiempo completo desde entonces. Mi idea es ponerlo a votación en Greenlight en una o dos semanas como máximo. El argumento es bastante sencillo: eres el capitán de una nave militar. Los mundos exteriores han declarado la guerra a la Federación Galáctica y todas las naves militares, incluida la tuya, reciben la orden de dirigirse a la capital y defenderla del inminente ataque. El juego en sí, es muy parecido al planteamiento de FTL. Hay un mapa estelar generado aleatoriamente con diferentes puntos a los que podemos saltar, cada vez que saltamos a un nuevo punto aparecerá un evento en el que podremos tomar decisiones. Dependiendo de la suerte y nuestras elecciones podremos ganar o perder créditos, moral, tripulantes, ganar nuevos sistemas o armas para la nave o hacer que el evento termine en una batalla. Algunos eventos son sencillos y tienen solo dos finales posibles o incluso solo uno (por ejemplo, los eventos que siempre finalizán en una batalla), pero otros serán bastante más complejos, el más variado hasta ahora tiene 9 finales distintos y 35 strings de texto. El sistema de batalla no se parece en nada al de FTL y es más parecido a Starpoint Gemini o al de Battlevoid Harbinger (pero en 3D). Las naves tienen puntos en los que se pueden acoplar sistemas y armas, las armas disparan y apuntan automáticamente y nosotros controlamos el movimiento de la nave, el control de energía y las habilidades que ofrecen algunos sistemas y armas y que tienen un tiempo de recarga una vez se utilizan (por ejemplo: camuflaje óptico, reparación, sabotaje de sistemas enemigos, lanzamiento de misil nuclear etc.). He grabado un gameplay de 15 minutos para que podáis ver un poco el juego. Ahora mismo el juego está en pre-alpha, tiene la mayoría de sistemas acabados, aunque algunas cosas pueden variar pero principalmente le falta contenido (eventos, naves, armas y sistemas), que es a lo que me dedicaré a partir de ahora. En el estado actual se puede jugar el primer nivel de los 5 que tendrá una partida completa. Pongo también algunas capturas más: Decidme como lo veis y que os parece!
  29. 6 points
    Hola foreros! Llegó el gran día. Por fin tenemos publicado nuestro primer juego, Medieval Business Clicker. Nos estrenamos en este mundo con mucha ilusión y metas por cumplir, deseando empezar con el siguiente proyecto, hacer colaboraciones y conocer gente para aumentar la plantilla y poder así aspirar a otros más ambiciosos. Os animamos a que lo probéis y veáis el resultado de varios meses de trabajo duro. Si nos dais vuestra bendición en forma de estrellas también os lo agradeceríamos mucho. Medieval Business Clicker es un adictivo juego incremental para android y PC (Próximamente en IOS) en el que tendrás que gestionar diferentes negocios y optimizarlos al máximo. Descárgalo gratis en android (pronto en PC e IOS): https://goo.gl/TyfCFY Comienzas tu aventura en un reino con diferentes negocios en los que invertir. Al principio el progreso completamente “manual”, pero en poco tiempo, el juego alcanzará un nivel mucho mas frenético. Además de comprar diferentes negocios, puedes contratar managers para automatizar los negocios, conseguir mejoras para mejorar el rendimiento, hacer diferentes misiones e incluso viajar a otras a zonas. Ademas incluye la posibilidad de elegir entre 3 personajes distintos y conseguir logros únicos para cada uno de ellos a lo largo de la aventura. Y un sistema de rejugabilidad infinita a través de reseteos que te otorgan un bonus en cada nueva partida en forma de "prestigio". Podéis preguntarnos cualquier duda sobre el desarrollo en este mismo post. Y estar al tanto de las novedades sobre MBC y nuestros futuros proyectos en : http://www.partyheadstudio.com Capturas de PlayStore de Medieval Business Clicker:
  30. 6 points
    SEEVN ahora está disponible para Android: https://play.google.com/store/apps/details?id=co.wcu.seevn Además puede descargarse para sistemas de escritorio en: https://wcu.itch.io/seevn POST ORIGINAL Aquí les va mi último proyecto en Unity. SEEVN es un editor de novelas visuales por nodos, que permite a los autores crear historias con múltiples rutas de manera más sencilla. Después de varias semanas de trabajo está listo para publicarse. Este ha sido uno de mis proyectos más motivantes. Aunque existen varios assets para creación de novelas hice este de comienzo a fin con sólo la API de UI. La primera versión es bastante básica, pero tengo una tonelada de características por implementar. Dejen sus comentarios. Veremos si genera algo de atención…
  31. 6 points
    Te dejo algo que arme hace un tiempo y lo modifique ahora para vos.. public static class Parabolic { public struct Node { public Vector3 Point; public Vector3 Euler; public Quaternion Rotation { get { return Quaternion.Euler(Euler); } } } public enum ERotation { Deg0, Deg90, Deg180, Deg270, } public static Node[] Create(Vector3 point, Vector2 velocity, int segments, ERotation rotation) { float vel = Mathf.Sqrt((velocity.x * velocity.x) + (velocity.y * velocity.y)); float angle = Mathf.Rad2Deg * (Mathf.Atan2(velocity.y, velocity.x)); float time = ; time += 0.1f; Node[] path = new Node[segments]; for (int i = ; i < segments; i++) { float disX = vel * time * Mathf.Cos(angle * Mathf.Deg2Rad); float disY = vel * time * Mathf.Sin(angle * Mathf.Deg2Rad) - (Physics2D.gravity.magnitude * time * time / 2.0f); path[i].Point = new Vector3(point.x + disX, point.y, point.z); if (rotation == ERotation.Deg0) path[i].Point.y += disY; else if (rotation == ERotation.Deg90) path[i].Point.z += disY; else if (rotation == ERotation.Deg180) path[i].Point.y -= disY; else if (rotation == ERotation.Deg270) path[i].Point.z -= disY; path[i].Euler = new Vector3(, , Mathf.Atan2(velocity.y - (Physics.gravity.magnitude) * time, velocity.x) * Mathf.Rad2Deg); time += 0.1f; } return path; } } Podes armar parabólicas en las 4 rotaciones creería necesarias para tus mecánicas. Te dejo un componente de prueba... public class Parabola : MonoBehaviour { public Vector2 Vi = new Vector2(10, 20); public Parabolic.Node[] Path = new Parabolic.Node[]; public int Segments = 50; public Parabolic.ERotation Rot = Parabolic.ERotation.Deg0; private void Update() { if (Input.GetKeyDown(KeyCode.Mouse0)) { Path = Parabolic.Create(transform.position, Vi, Segments, Rot); } } private void OnDrawGizmos() { for (int i = ; i < Path.Length - 1; i++) { int i2 = i + 1; Gizmos.color = Color.white; Gizmos.DrawLine(Path[i].Point, Path[i2].Point); Vector3 dir = (Path[i].Point + Path[i2].Point.normalized); Vector3 hDir = dir; hDir.y = Path[i].Point.y; Vector3 vDir = dir; vDir.x = Path[i].Point.x; Gizmos.color = Color.red; Gizmos.DrawLine(Path[i].Point, hDir); Gizmos.color = Color.blue; Gizmos.DrawLine(Path[i].Point, vDir); } } } Espero te sirvan!
  32. 6 points
    24 Code Limit, tiene el placer de anunciar su nuevo proyecto. Proyecto Gratuito que saldrá en primer lugar para Android y en breve para iOS. ___________________________ Actualización ____________________________________ https://play.google.com/store/apps/details?id=com.CodeLimit.ShootyHeroes http://www.amazon.com/Shooty-Sky-Héroes-Endless-Arcade/dp/B019Z93KCQ/ref=sr_1_1 https://itunes.apple.com/es/app/shooty-sky-heroes-endless/id1067640076?l=en&mt=8 https://www.microsoft.com/en-us/store/games/shooty-sky-heroes/9nblggh5km34 Hasta tenemos review ^^ que triste xD A raíz del resurgimiento de la moda de los Shoot` em up con nuevas estéticas de tendencias voxel o cubicas o pixel hemos decidido llevar a cabo este proyecto, si bien no el mas ambicioso, pero si donde mas cariño hemos puesto. Por supuesto gracias a la colaboración de ciertos miembros del foro por sus aportes ante problemas lógicos, hemos podido llevar a cabo este proyecto en prácticamente 2 meses a un estado casi finalizado. Lo aprendido en anteriores proyectos nos ha servidor para ir creando contenido cada vez a una velocidad mayor. También técnicas básicas con el soporte de extensiones para creación de pool del Sr. Ilie se ha convertido en una clase básica en nuestros proyectos para lograr rendimientos significativos sobre todo en terminales de gama media media-baja. El objetivo del juego en el primer lanzamiento será del clásico modo insane donde te vendrán oleadas de enemigos desde todos los flancos menos el inferior, y tendremos que eliminarlos si no queremos acabar secos. Cada cierto tiempo podremos potenciar nuestras armas con powerups amen de habilidades especiales para cada personaje, aunque en un principio tendremos el clásico carga de misiles si no te mueves durante un periodo. Si logras avanzar hasta cierto punto deberás enfrentarte a un final boss con ataques especiales y mas vida clásico en cualquier shoot em up que se precie. Nuestro objetivo en esta semana es calibrar la dificultad y el ritmo de juego para hacerlo lo mas divertido posible. En las próximas semanas queremos plantear una serie de retos/niveles con buenas recompensas que incentiven a superarlos y siempre sin dejar un ritmo frenético y divertido. Hemos optado por la clásica estética voxel con personajes famosos, pero obviamente cambiando nombres para no violar copyright, el objetivo en los próximos días será aumentar el número de enemigos y jugadores a conseguir. De momento contamos con una variedad simple de sonidos FX que iremos ampliando y mejorando en breve. Si habéis conseguido leer hasta aquí, gracias por vuestra atención sincera. También necesitamos todas las críticas posibles, tanto buenas como malas, siempre bajo nuestro criterio, esperamos acertar con la que tomaremos para cambiar el rumbo en determinados aspectos. Pero gracias lo primero a todos por comentar. Todo el diseño gráfico fue realizado por el maestro Gustavo Schreyer y la programación por parte de Francisco Gimenez. Hemos contado entre otros con la inestimable colaboración del estudio de Keplrerians. Si me dais unos minutos empiezo a subir imágenes..... Enlace a la comunidad de Beta Tester para quien nos complazca con su participación. Porque también queda gente en la red social de Facebook, Shooty Heroes... Bueno, en breve podéis uniros en Beta tester en Google y subiré apk en Dropbox también por aquí. Un saludo.
  33. 6 points
    Hola a todos He estado trabajando con el tema de Pathfinder para mi proyecto y quería compartir lo que he conseguido hasta ahora. No es el A* pathfinder, pero es muchísimo más sencillo. Esta basado en el algoritmo que posteó un usuario del foro, el código del algoritmo estaba escrito en C++ Código en C++y lo traduje a javascript. El algoritmo esta basado en una Matriz como el A* pathfinder He estado observando la idea de escanear el terreno y dividirlo en cuadriculas de un compañero del foro que está realizando el A* Pathfinder. En mi proyecto también escaneo el terreno pero de manera diferente. Lo que se me ocurrió fue crearme una Matriz de Objetos (Planos en este caso). El nombre de cada cuadrícula (Objeto) de la matriz me indica las coordenadas que ocupa en dicha matriz. Así el punto (0,0) tendrá de nombre "0000", el punto (0,1) será el "0001". Los dos primeros caracteres me indican la coordenada x y los siguientes la coordenada y. Recupero ese nombre lo paso a Entero y lo uso para trabajar con la Matriz lógica . Mejor veis el código y lo probais: El algoritmo funciona perfectamente en escenarios como el que hay en el proyecto. Con los laterales libre de obstáculos. El problema es que en escenarios con laterales cerrados el Player puede fallar al encontrar el camino. Esto es algo que hay que mejorar. PATHFINDER.zip
  34. 6 points
    Buenas tardes a todos! Ya he hecho una presentación del juego en el apartado de Proyectos Finalizados, pero esta vez quiero compartir con vosotros, desarrolladores como yo, unas líneas sobre el cómo hice mi proyecto: Mobius of Magic, un RPG de la vieja escuela adaptado para dispositivos táctiles. El hecho es que he dedicado más de un año a tiempo completo a este proyecto y me gustaría compartir mi experiencia con todos aquellos que quieran aventurarse a hacer lo mismo (o simplemente con aquellos que les pique la curiosidad). Por esta razón he escrito este libro. Un libro poco convencional donde expongo a lo largo de más de 40 páginas, el proceso entero de la creación de Mobius of Magic. No es un tutorial, puesto que de tutoriales de Unity hay para hacer mil hogueras. He intentado escribir este libro buscando un poco el lado más humano del desarrollo: ¿Qué materiales he usado? ¿Por qué? ¿Qué software? ¿Cómo hice el diseño de personajes? ¿Y la IA de los enemigos? ¿Cómo era el prototipo del videojuego? ¿Cuál era mi idea original? He intentado responder a todas estas preguntas (y muchas más) que uno se hace cuando inicia su aventura de crear un juego, intentando siempre mantener los costes al mínimo y buscando la balanza entre un juego ambicioso pero no imposible de realizar. Espero que disfrutéis del libro. És gratuito y podéis encontrarlo en la iBooks Store de Apple (para iPad). Siento que no esté disponible para otras plataformas, pero quería incluir videos, modelos 3D y todo tipo de materiales gráficos. Para ello necesitaba una plataforma que me permitiera hacer todo eso, y sólo lo podía hacer mediante iBooks Author. Link al Libro Happy coding!
  35. 6 points
    Buenas. Os presento la nueva versión de mi Formula Unlimited....Es un juego nuevo, no un update del anterior...... Pero entonces, ¿que hay de nuevo en este? Mucho más espectacular que la Formula 1 y GP 2. En esta nueva versión estaremos al volante de fabulosos monoplazas de alto rendimiento. Un juego de competición de alto nivel, con monoplazas exclusivos y con un rendimiento muy superior a un F1 convencional. Google Play: Formula Unlimited 2014 App Store: Formula Unlimited 2014 Novedades con respecto a la versión anterior: - Lo primero es la cámara. Ahora es tercera persona y estudiaré la posibilidad de tener la misma vista que la primera versión (en primera). - Perdida de rendimiento y aerodinámica por impactos y degradación de neumáticos. - Indicador de Status del monoplaza. - Parada en boxes para restablecer estado de vehículo y neumáticos. Por consiguiente ahora los circuitos disponen de PitLane - Ajuste de sensibilidad en pantalla de juego durante la carrera. - Mejoras gráficas en el monoplaza del player y en los monoplazas IA. En estos últimos si que hay una gran diferencia con respecto a la anterior versión. EDITADO: Cambios en estilo del Menú de configuración del Monoplaza Muestra parada en boxes (Los cambios de ruedas se realizan de manera táctil)
  36. 6 points
    Yo comenze un proyecto solo pero ahora me acompaña gente en el camino de construir un RTS. Concept Art: Unity
  37. 5 points
    Unity cada vez que creas un nuevo script, sea del tipo que sea, siempre consulta un archivo plantilla para generarlo. Por eso siempre tenemos añadido, por ejemplo, la función Start y Update, o creada la clase en función del nombre que le pongas al Script. Pero eso puedes modificarlo fácilmente. Simplemente dirígete a la siguiente ubicación: Será diferente según la versión de Unity que uses. Ahí podemos ver todos las plantillas, simplemente abrimos la que queramos modificar. Ahora podéis añadir una cabecera de Copyright o quitar las funciones Start y Update (que si no hay que tenerlas vacías). Ya las añadirás tu cuando las tengas que usar. Espero que os sea útil. Hasta la próxima
  38. 5 points
    Buenas, Si queréis reíros un rato de un español hablando inglés :) aquí os dejo el link del tutorial que he hecho de cómo creé mi juego: How to Do your First 3D Game in Unity (2018) - Advanced Features Explico cómo hacer cosas que quizás os pueden interesar como: Map Level Builder (el que yo me he hecho usando photoshop y xml) Unity Ads Save & Load data Audio Manager Ya me diréis qué os parece, que es mi primer tutorial, y por encima en inglés, aunque hablo sencillito del todo :) Saludos
  39. 5 points
    Hola a todos, Desde MoadStudio llevamos dándole vueltas a un juego de carreras con estéticas Low Poly con un toque ochentero en cuento a vehículos se refiere, y en el que estamos incorporando varios modos de carrera como TimeLap, Race, Battle, e incluso mini juegos sorpresas a desbloquear. Actualmente disponemos ya de varios circuitos y coches, corriendo con un buen framerate en móviles y tablets, y esperamos tenerlo pronto en googleplay. Os dejo algunos videos donde se puede ver mecánicas y gameplay. Las música de los mismos son del compañero de Batallas Igor, que ademas programar le da al tema musical Saludos!! ---- Moisés Moreno - MoadStudio www.moadstudio.com @moadstudio Google Play
  40. 5 points
    Hola a todos! Me llamo Oscar y soy coordinador del programa de incubación de empresas de videojuegos GameBCN, que se desarrolla en Barcelona. Nuestra labor consiste en acompañar a 5 equipos durante 6 meses en el desarrollo de sus juegos. Para ello proporcionamos gratuitamente: Espacio de trabajo en nuestro coworking Formaciones diversas (producción, game design, level design, marketing, monetización...) Expertos de la industria vienen a mentorizar a los equipos Les ponemos en contacto con publishers e inversores Si alguno de vosotros está desarrollando un juego, seguramente en setiembre abriremos una nueva convocatoria. Saludos!
  41. 5 points
    Hola, hago este mini articulo porque hace unos dias me di cuenta que Unity ahora o desde hace poco trae un plugin de audio encargado de hacer lo que se llama HRTF (Head Related Transfer Function), que basicamente simula una fuente de audio en el espacio en relacion a una cabeza (Audio Listener de la camara preferentemente). Se dice Cabeza porque se vale de la diferencia en los tiempos de ingreso de ondas a cada oido para dar esa sensacion de "viene de alla", como en la realidad lo hace el cerebro, ... a diferencia del audio por default que solo calcula un vector de distancia y en base a las componentes divide el audio en Izquierda y derecha, quitando todo 3D aunque diga sonido 3D. En definitiva para aplicarlo a un proyecto hay que: --> Ir a opciones de Audio (Edit/Projects Settings/Audio) y elegir un plugin de la lista correspondiente a "Spatializer plugin" (A mi me va mejor el MS HRTF Spatializer, el otro sale muy bajo el volumen): --> En los AudioSources que se desea el efecto se lo habilita en el inspector (opcion Spatialize): Listo Ahora unas pruebitas (Ver Audio - DSP Load, algunos valores oscilaban en +-1 o 2 % de carga DSP): sin plugin 2 fuentes/ 40 fuentes/ 240 fuentes: con plugin 2 fuentes/ 40 fuentes/ 240 fuentes: En todos los casos los fps no hicieron la diferencia, (salvo cuando puse como 1000 pero supere la capacidad del plugin porque hubo unos warnings por ahi), aunque si la hizo el DSP Load como es de suponer. En conclusion si se tiene un escenario con demasiadas fuentes de audio lo mejor es siempre dar prioridad a aquellas importantes, como lo pueden ser pasos, voces, un enemigo, una fuente que su localizacion espacial sea de importancia (sobre todo si se tiene un horror game!!) y este tipo de plugin hara maravillas y a un costo relativamente bajo para el gran efecto que produce. PD: Usar auriculares por favor
  42. 5 points
    Parece ser que Unity ha comprado el asset y lo ha puesto gratuito para todos. La diferencia entre el de pago y este es sencillamente que viene empaquetado en una dll el código fuente, sin embargo la funcionalidad es exactamente la misma. https://www.assetstore.unity3d.com/en/#!/content/84126 Saludos
  43. 5 points
    ¡Hola de nuevo a todos! Estamos contentos de anunciar de que Vaccine War ya esta a la venta en Steam. Aprovechad que tiene un descuento del 25% hasta el dia 27 Deseamos que lo disfruteis y que podais ayudar a Daniel en su cruzada.
  44. 5 points
    Hola a todos! Les presento mi ultimo proyecto, es un juego para móviles por el momento esta disponible solamente para android pero pronto estará también para iPhone. el nombre es "Speedbox" un poco trivial lo se, los controles son muy sencillos (Derecha,Izquierda y voltear) pero la jugabilidad es un poco 'Hardcore', ya que esa era el objetivo, los gráficos son desentes para ser un juego móvil, la interfaz gráfica muy limpia y diseño plano con un esquema de color suave. Cuenta con dos modos de juego "Classic" donde el objetivo principal es recoger los 'items' del nivel y "Infinity" donde tienes que llegar lo mas lejos que puedas evitando los obstaculos. esta es la primera versión, tengo planeado integrar a leadeboard / ranking para la próxima actualización para compartir las mejores puntuaciones. Espero le den una mirada y me den sus consejos para mejorar, una buena evaluacion me ayudaria mucho chicos! Google Play Store: https://play.google.com/store/apps/details?id=sv.lovattostudio.speedbox Les dejo unas capturas y un video de el juego en su etapa de desarrollo (hay muchas mejoras en la version de lanzamiento).
  45. 5 points
    Buenas, aquí muestro 2 primeras imágenes del segundo juego de JeicoGames, Catch the cells (Atrapa las células) donde el jugador deberá encerrar las células en membranas de diferentes formas siempre y cuando las células tengan algo en común ya sea color, citoplasma o núcleo, todavia falta mejorar las graficas y crear los menus, apenas llego 50 niveles y voy subiendo hasta llegar a 100 niveles
  46. 5 points
    Empieza por esto: void Start() { Debug.Log("Hello World!"); }
  47. 5 points
    oye aki te traigo un adelanto del trabajo a ver que te parece
  48. 5 points
    Estás t0nto, si le mandas el móvil con que vas a hablar? mándale el número nada mas!
  49. 5 points
    Buenos días a todos comunidad UnitySpain! Vengo a presentar mi primer juego: Mobius of Magic! Una aventura ambientada en un mundo de fantasía donde coexisten 5 gremios de magia oficiales (y otros, pero esto os lo dejo para descubrir a vosotros ). Tu aventura empieza tras finalizar tu entrenamiento como aprendiz de Hechicero. Tras completar unas pruebas en forma de tutorial, tu maestro, el Hechicero Roku, te pide el encargo de llevar una misteriosa reliquia a Leena, maestra de Magia Blanca, en la ciudad de Waynima. Pero mientras completas esta tarea, un misterioso mago encapuchado está moviendo tierras y mares para conseguir esta reliquia. ¿Quién es este misterioso mago encapuchado? ¿Que secretos encierra la reliquia del Colmillo del Dragón? Estas son las principales características del juego: Lucha contra tus enemigos con un sistema de combate por turnos, pero dinámico e innovador: Los ataques se realizan mediante gestos.Explora el mundo de Everwind! Visita pantanos, cuevas, ciudades llenas de vida, bibliotecas arcanas, montañas encantadas, bosques profundos y muchos más!Aprende el arte de la magia de los diferentes maestros de cada gremio y desvela la épica historia detrás de la misteriosa reliquia del Colmillo del Dragón!Equípate con diferentes objetos mágicos (anillos, collares y muñequeras) y lucha junto a hasta 2 únimos, unas bestias místicas que te ayudan en combate. Trailer de lanzamiento: Click aqui! - Descargar en Android PlayStore - Descargar en Apple AppStore (iPhone & iPad) Si tenéis alguna sugerencia, estaría encantado de escucharla! Y ya para acabar, para celebrar el lanzamiento de Mobius of Magic, pongo aqui algunos códigos promocionales. Espero que lo disfrutéis! - W33NTTWATMAM- TNFJYX6XLYE9- APHPWAT937RM Happy coding!
  50. 5 points
    Estoy algo atorado con Last Bullet porque el artista se ha atrasado un poco así que estoy esperando que termine para seguir con ese proyecto. Por mientras, esta es una de las imágenes que me ha mandado (para el menú e íconos): Mientras tanto estoy juntando assets y escribiendo el documento de diseño para mi próximo proyecto que va a ser un juego sci fi espacial con niveles procedurales y aún no me decido si combate por turnos a lo JRPG, un "tablero" con hexágonos (a lo Heroes of Might & Magic) o derechamente voy por algo en tiempo real (como Homeworld). Como ven, tengo muchas dudas, lo único que tengo claro es que tiene que ser un juego para PC porque estoy harto de juegos para móviles (desde ahora voy a tratar de sólo hacer juegos que yo estaría dispuesto a comprar y jugar). Screenshot de una prueba que estoy haciendo (el proyecto está recién en planeación): Saludos.
UnitySpain © Todos los derechos reservados 2020
×
×
  • Create New...