Jump to content
UnitySpain

Aceptamos donaciones vía Paypal.

UnitySpain.com es un servicio gratuito, pero mantener la Comunidad conlleva una serie de gastos.

Fondo Anual Unityspain: Donados 15,00€ de 150,00€

  • Servidor: Dominio.com y Hosting Web
  • Mantenimiento de los Foros
  • Contenido y Servicios Extras
  • Mantenimiento para Redes Sociales

Leaderboard


Popular Content

Showing most liked content since 01/18/2020 in all areas

  1. 5 likes
    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!
  2. 4 likes
    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!!
  3. 3 likes
    Hola a todos,me alegra volver por aquí. Quería enseñaros el proyecto que tengo entre manos, esta en desarrollo y las texturas ni siquiera están bien tileadas, pero ya tengo el escenario mas o menos montado a falta de muebles, plantas y bastantes detalles. Los sonidos de momento tampoco están, me esta costando bastante encontrar. No tengo prisa en acabarlo así que seguramente va para largo, pero cuando lo acabe quiero que tenga bastantes detalles. Si alguien se le ocurre algo que pueda ir bien en el estilo del juego o alguna sugerencia, se agradecería. Si se os ocurriera también algunos assets de la store que me pudierais recomendar seria estupendo. como ya habréis visto algunos modelos los he descargado y otros los he hecho yo. En principio quiero que el juego se base en encontrar llaves y abrir puertas, rodando el mismo mapa. tambien me falta un adaptador de kineckt para el ordenador para dar vida a las animaciones. Un saludo a todos.
  4. 3 likes
    muy pro la documentacion, no esperaba menos de @lightbug (no esperaba menos de 200 paginas XD) no sabia que habias continuado con tu character controler (conocia la version 2d) ...pero ahora has completado tu complemento con un completo y funcional 3D... muy pro todo.... ...este @lightbug es muy pro... dan ganas de secuestrarle y encerrarle en una habitacion a teclear codigo... digo... estaria guai colaborar con el en algun proyecto...
  5. 3 likes
    Hola @nomoregames te aconsejo que antes de empezar a intentar realizar un juego al 100% aprendas, técnicas, formas, algoritmos que suelen utilizar los desarrolladores de juegos. Aprendizaje Básico: Entender las estructuras de datos simples de C# Entender los delegados y eventos Aprender sobre NameSpace, Clases, Estructuras y Niveles de Accesibilidad. Aprender sobre Clases Abstractas Aprender sobre funciones Virtuales Aprender a utilizar Switch Aprender a utilizar Enumeradores Aprender a utilizar Linq, ventajas y desventajas Entender los vectores Aprender y utilizar vectores de dirección Entender las posiciones, rotaciones, escalas tanto globales como locales Aprender el ciclo de vida de una objecto en C# Aprender el ciclo de vida de un componente Entender MonoBehaviour Aprender a realizar Herencias Aprender a serializar clases Aprender a utilizar BinaryWriter y BinaryReader. Aprender a trasladar objetos a diferentes velocidades. Aprender lo básico sobre componentes físicos (Rigidbody) Aprender fórmula de tiro parabólico. Aprender fórmula de curva bézier. Aprender sobre Raycast, Box , Sphere, Line, Ray y todas sus variantes. Aprender sobre prefabs y el nuevo flujo de trabajo con nested-prefabs. Aprender a utilizar Singleton Aprender a utilizar Atributos de clases. Aprender a utilizar Scriptable Object para la fragmentación de comportamiento datos. Aprender sobre Listas, Arreglas Aprender sobre variables de sólo lectura Aprendizaje Avanzado: Aprender sobre funciones arrow Aprender sobre funciones lambda Aprender a utilizar correctamente Dispose y Garbage Collection Aprender a utilizar Dots. Aprender a utilizar HLSL (Surface Shaders) Aprender a utilizar Partículas Aprender a utilizar Sockets Aprender a utilizar WebClients Aprender a utilizar Threads Aprender algoritmos de búsquedas de camino Pathfinding como A* Actividades: Crear un sistema simple de WayPoints Crear un sistema de seguimientos de WayPoints mediante direcciones y fuerza Hacer un seguimiento de cámara simple Simular la gravedad de una caja sin rigidbody. Calcular la fuerza exacta para lograr el salto de 1 unidad con rigidbody. Generar un Cubo mediante Código con MeshRenderer. Guardar y Cargar datos en formato binario. Simulador de vuelo de un avión sin Rigidbody. Simulador de vuelo de un helicóptero sin Rigidbody. Simulador de vuelo de un avión con Rigidbody. Simulador de vuelo de un helicóptero con Rigidbody. Movimiento simple de jugador 2D sin rigidbody. Movimiento simple de jugador 2D con rigidbody. Movimiento simple de jugador 3D sin rigidbody. Movimiento simple de jugador 3D con rigidbody. Movimiento simple de jugador 3D con CharacterController. Detectar si el Jugador está en contacto con el suelo. Calcular el tiempo que el jugador estuvo en el aire. Calcular el tiempo que el jugador estuvo en el suelo. Calcular la fuerza necesaria vertical y horizontal para que un objeto sin Rigidbody recorra 10 unidades con una fuerza gravitatoria de -10 en el eje Y. Detectar si el Jugador está en contacto con la pared (que se encuentre por delante). Detectar si el Jugador está en contacto o próximo a un objeto sobre su cabeza. Evitar que el Jugador salte si no tiene el espacio suficiente. Generar zonas con diferentes comportamientos físicos, como deslizarse, alentar, acelerar, rebotar. Controlar la velocidad de Jugador para que recorra 100 unidades en línea recta siempre al mismo tiempo. Diseñar UI mediante editor (Edit Mode). Diseñar UI mediante código (Runtime). Proyectos para aprender sobre mecánicas: Intenta replicar las mecánicas de la forma más exacta posible, luego modificarlas para experimentar y entender el por que se llegó a la decisión de mantener esos valores. Memo Puzzle Rompecabeza Pong: https://es.wikipedia.org/wiki/Pong Snake: https://es.wikipedia.org/wiki/La_serpiente_(videojuego) Tetris Arkanoid Pacman Space Invaders Super mario bros (Mecánicas) The legend of zelda (Mecánicas) Infinity Runner (Mecánicas) Half-Life 1 (Mecánicas) Proyectos NO RECOMENDADOS: RPGs MMO ROL el clásico "GTA" Juegos Multiplayer como BF, Fornite, etc.. Links para estudio y practicar: son los que me acuerdo que leí en algún momento y me han servido, los de CEDV son muy buenos, lamentablemente ahora se pasaron a Unreal, pero siguen estando las ediciones del 2015 https://openlibra.com/es/book/download/desarrollo-de-videojuegos-un-enfoque-practico-3a-ed/ https://openlibra.com/es/book/download/desarrollo-de-videojuegos https://openlibra.com/es/book/download/logica-del-videojuego http://cedv.uclm.es/libro2015/M4.pdf Esto está destinado a todos los usuarios que se encuentren estancados.
  6. 3 likes
    si quieres hacer que la cabeza mire a un sitio en concreto debes hacerlo en "LateUpdate", ya que el orden seria: -Update -Animacion -LateUpdate entonces si mueves un "hueso" en Update, luego la animacion te lo "pisa", recoloca los huesos como manda la animacion... pero si lo haces en "void LateUpdate()" entonces tu "pisas" la animacion y recolocas el hueso como quieras
  7. 3 likes
    El Standard Shader de las últimas versiones de Unity soporta varios métodos. La propia doc de Unity es bastante decente en este sentido: Llaman bump mapping al normal mapping, pero dejan claro que es algo informal, y que "normal mapping" es un tipo de bump mapping. El Standard Shader ahora soporta "height maps" y "occlusion maps", que son también técnicas de bump mapping. Además no son exclusivas. Normal Maps (o en unity, simplemente "Bump maps"): Afectan al ángulo de la luz al rebotar sobre la superficie, y nos permite dar sensación de relieve que se comporta corectamente respecto a la iluminación. En esta página hay un apartado llamado "What’s the difference between Bump Maps, Normal Maps and Height Maps?" Unity acepta texturas black and white y las convierte internamente a RGB (normales X, Y, Z) para los normal maps. Height Maps (o Parallax Maps): Al contrario que los normal maps, que trabajan sobre la luz, los Height Maps calculan realmente el pixel desplazado donde estaría de acorde al relieve, haciendo que píxeles más cercanos aparezcan más grandes respecto a la cámara. Además, las partes con más relieve taparán a las de menos relieve. Es más costosa para la GPU. Se usan a menudo junto a Normal Maps. La fuente es una textura en grises. Occlusion Maps: Afectan a la cantidad de luz indirecta que debe recibir cada parte del material. Recomiendo encarecidamente leer las tres páginas. Aquí debajo tenemos: 1) Albedo 2) Albedo + Normal 3) Albedo + Normal + Height Observa, sin embargo, que ninguna de estas técnicas permite que los bordes de los polígonos presenten relieve. Esto no se puede hacer en una GPU, y el ejemplo de la bola que muestras arriba parece otra técnica llamada "displacement mapping", que Unity no soporta de serie.
  8. 2 likes
    Diferencias Usas raycasting cuando quieres saber a qué distancia o qué objeto impacta con un un segmento de línea. Así sabemos qué tenemos delante en la dirección de interés. Ese segmento lo defines en el momento de calcular el raycast, así que puede ser lo que tu quieras (pero por cada rayo que calculas, incurres en un coste computacional). Se pueden usar para: Calcular la distancia al suelo desde un punto (rayo hacia abajo) para posicionar objetos o cámaras. Calcular el lugar donde impacta un disparo "instantáneo" (rayo desde el cañón de un arma). Calcular en qué objeto está apuntando el ratón. Calcular qué objetos "ve" uno de nuestros personajes o vehículos (se suelen calcular unos cuantos rayos alrededor para saber si vamos a colisionar con algo). Fíjate que puedes proyectar rayos para calcular la distancia a objetos con los que aún no se está colisionando. Y recuerda también que además del Raycast, tienes el Spherecast y otras variantes, porque una línea es muy fina, y a veces necesitamos proyectar una "esfera" para saber si hay algún objeto en la dirección de interés. Las colisiones en Unity en cambio son resueltas por el motor durante la simulación física, y necesitan que haya un Rigidbody involucrado (ya que los Rigidbody son los objetos con los que trabaja el motor físico). Sólo obtendrás colisiones entre Ridigbody y objetos que tengan un Collider de algún tipo. Las colisiones se pueden gestionar como eventos, así que Unity llamará a OnCollide cuando se produzca una colisión. Además, los Collider pueden marcarse como "Trigger", lo que causará que no se comporten como sólidos, sino que puedan ser atravesados (en este caso, Unity llamará a OnTriggerEnter). Esto se puede usar para saber cuando uno de nuestros objetos físicos impacta con algo o atraviesa un "trigger".: Saber cuando un personaje u objeto entra en determinado área. Reproducir sonidos en las colisiones entre objetos. Saber cuándo un personaje u objeto toca a otro o una parte del escenario. Cuál usar para un character controller Parece que no es muy recomendable usar el motor físico para controlar un personaje a no ser que la simulación del movimiento en sí misma deba ser físicamente realista. Yo en general opino parecido, pero cada caso varía. El motivo principal de no usar el motor físico, en mi opinión, para esto, es que tendrías que modelar el movimiento del personaje usando fuerzas, rozamientos, materiales... y gestionar los tropiezos y caídas (superficies inclinadas, etc). Esto puede tener sentido en algunos proyectos pero en general complica lograr un movimiento consistente. Por otra parte usar uno o unos pocos Raycast es más rápido que dejar que el motor físico mueva tu personaje, aunque esto no tiene un gran impacto si el collider de tu personaje es una simple cápsula.
  9. 2 likes
    Francoe1, es un lujazo ver a Don Gonzalo usar su espada para disparar la llama de poder en el Build. El disparo funciona perfectamente. Aunque ahora tengo que lidiar con otros problemas más (casi todos los scripts están construidos con la misma lógica que éstos), los intentaré lidiar con los conocimientos y consejos que he aprendido con tu ayuda sobre public static, los get; set; y las instancias. A ver si puedo apañármelas. Te estoy eternamente agradecido. Mil Gracias de nuevo. PD.: No se descarte un próximo post con más quebraderos de cabeza!
  10. 2 likes
    En PC juego con mando o ratón/teclado. Desde el FIFA, Need for Speed, Battlefield V, RDR2, bueno decenas. En Android cero patatero. Mírate esta web que contiene detalles de cada app en steam, sus ventas, jugadores, etc: https://steamdb.info/
  11. 2 likes
    Es lo primero que he hecho pero no me entero porque no explican las cosas paso por paso, por ejemplo, ¿cómo se llega a esta ventana?: Te dejo el link de esta página, no lo compartas, es ultra secreto, lo saque de la deep weeb pero aporta una información vital sobre AnimatioView Link del infierno Link del Infierno X2 También quiero que sepas que existe una web a dia de hoy algo conocida, desarrollada especialmente para buscar eso que no sabemos ni como se llama Link a la página mágica.
  12. 2 likes
    Es recomendable utilizar una extensión de IList que soluciones el problema, no por rendimiento, si no para mantener orden y que el código se más fácil de leer. public static class System.Generic { public static void Shuffle<T>(this IList<T> list) { Random random = new Random(); int n = list.Count; for(int i= list.Count - 1; i > 1; i--) { int rnd = random.Next(i + 1); T value = list[rnd]; list[rnd] = list[i]; list[i] = value; } } } De este modo puede utilizar la extensión en cualquier lista dentro del código. private void SetData(List<Item> items) { items.Shuffle(); }
  13. 2 likes
    Hola amigos. Hace ya un año publique mi herramienta de localización CGLocalization en el Asset Store. Ahora está en la versión 1.1 con algunas mejoras y código fuente incluido. Ahora mismo estoy trabajando en otras Cree un blog específicamente para la herramienta donde publicaré los cambios que vaya implementando a la herramienta, documentación, tutoriales y más. Enlace al Blog: CGLocalization Blog Enlace al Store: CGLocalization Package Enlace a la versión free (Solo contiene ejemplos): CGLocalization Free Package Trailer:
  14. 2 likes
    Podrias compartir los errores o el archivo de debug del compilado. Esto puede deberse a que estas utilizando funciones que solo están disponible en una plataforma y/o el editor y por esta razón está generando errores el compilado.
  15. 2 likes
    @lightbug no voy a hacer quote de tu post por que se hace largo, pero estas en lo correcto, en el comentario "Es normal, me estresa un poco algunas cosas. Pero siempre intentaré tener respeto." Había escrito más explicando sobre el porqué de las cosas, la modularidad, los punteros de memoria y GC pero después de escribirlo me pregunte ¿Por que estamos compartiendo información de esta forma?. Cuando yo arranque en el desarrollo de juegos con previos conocimientos en programación tuve que estudiar y aprender muchas cosas, en esos tiempos en el foro estaba @Jocyf que compartía un material bastante llevadero, no se trataba de hacer una réplica del tutorial, si no, de la observación y la implementación de otras personas, luego, me di cuenta de la importancia del Open Source y lo gratificante que es empezar a apoyar proyectos en GIT. En todo mi camino desarrolle para grandes y chicas empresas , proyectos fáciles, complicados hasta fracase un par de veces pero nunca nadie me explico absolutamente nada, nunca me dijeron el "Por qué" se realizaba algo de cierta manera, siempre tuve que buscar la explicación por mi parte, esto no quiere decir que no exista gente sin ganas de compartir, de hecho en el foro oficial de Unity hay personajes que me han ayudado bastante con problemas que en ese entonces creía complejos. Me termine dando cuenta de algo, los programadores nuevos (no quiero generalizar) simplemente aprender a repetir. La programación es un ARTE y PASIÓN quienes lo comprenden son las personas que pasan horas y horas escribiendo código, intentando entender, aprender y optimizar todo al máximo, no importa que sepas como funciona, lo que importa es la experiencia que tenes para implementar el conocimiento en diferentes contextos. Dando la explicación anterior se puede deducir porque decidi no perder tiempo en contestar a esta persona y aprovecharlo en algo mejor. (Aca invertí mi tiempo) @Jhonatan00_00 No te lo tomes a mal, pero cuando no sabes de qué hablas, no tenes idea, es mejor no argumentar y menos aún intentar retrucar. Si quieres y realmente te gusta el desarrollo de juegos empieza por aprender y entender. En el topic hice 2 respuestas con soluciones, en la primera intente no invadir en la solución que el usuario encontró, esto es muy importante, cuando alguien te consulta algo tienes que responder siempre contextualizando el contenido según su conocimiento. La segunda respuesta es para ejemplificar que la problemática tiene una solución alternativa, más eficiente y la que se utiliza generalmente para resolver este problema, el incremento de una variable para este tipo de cosas es totalmente impracticable, inestable, inseguro, etc. Sin embargo, existen más formas aún, que se implementan en contextos diferentes, en conjunto con otros componentes que forman un sistema modular. En resumen, no quiero que se mal entienda, me gusta ayudar y compartir mi conocimiento, me gusta leer a otros usuarios, pero me rompe mucho lo huevos que se intente discutir sin argumentos y/o conocimientos. Saludos-
  16. 2 likes
    Si no mal recuerdo Mask Avatar aparece junto Animator Controller, version 4.0. Fíjate que deberías tenerlo, yo use mucho tiempo la 4.2.x y tenía Avatar Mask.
  17. 2 likes
    La idea está bien, la herramienta aún tiene mucho trabajo por delante, pero el núcleo parece bien encaminado. Cosas que agregaria. Posibilidad de crear muros fijando su ANCHO y ALTO Posibilidad de biselar borders. Simple sistema de auto guías. Manteniendo Shift que la línea esté en un ángulo recto Trabajar con curvas bezier. Temas, que las texturas tengan nombres genéricos y puedas crear temas, y puedes asignar cualquier tema en runtime, esto puede servir para ciclos de día y noche donde las luces cambian, cuando llueve, nieva, etc... Tambien para diferentes épocas festivas, como halloween, navidad, ... Creo que con esto estaría más que suficiente. El valor que le pondría al assets sería de u$d 35
  18. 2 likes
    En el animator existen Mask Avatar que son justamente para habilitar o deshabilitar el link de los huesos con la malla. https://docs.unity3d.com/es/530/Manual/class-AvatarMask.html Todo esto se llama IK (Inverse Kinematics) es un tema complejo a nivel matemático, pero Unity ofrece módulos que solucionan parte del problema. Recuerda que puedes utilizar OnAnimatorIK desde un componente que se encuentre en el mismo GameObject que AnimatorController para sobre escribir y crear tus comportamientos IK. animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, leftFootPositionWeight); animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, leftFootRotationWeight); animator.SetIKPosition(AvatarIKGoal.LeftFoot, leftFootObj.position); animator.SetIKRotation(AvatarIKGoal.LeftFoot, leftFootObj.rotation); Puedes asignar el peso del IK, mientras más cercano al 1 se encuentre menos fuerza tendrá la animación. Revisa esta sección, está perfectamente explicado y en español. https://docs.unity3d.com/es/2018.4/Manual/InverseKinematics.html
  19. 2 likes
    Hola, no soy un experto ni nada y además hace 1 año casi exacto que vendo assets, así que lo que digo agárralo con pinzas. Lo primero que sí tenés que hacer (fuera del tema del precio) es unirte en el foro de Publishers del foro oficial. No recuerdo si necesitas publicar primero o solo con registrarte como publisher te dan el pase. La cuestión es que ahí se discuten este tipo de temas y más. Un topic estaba orientado exactamente a esto, y un developer de Unity dejó este video: En definitiva no existe una respuesta 100% clara. El precio de algo (dentro de un contexto) acarrea la información de tu producto. Entra la cuestión de que somos seres caóticos y emocionales, y estamos dispuestos a comprar algo, no solo para usarlo, sino también para lucir y refregar en la cara lo que pagamos (o al menos creérnosla de que fue bueno, lo sea o no tanto). Es difícil decirte $ X estando muy seguro (esto debido a que internamente no conozco tu asset, y creas o no, todo vale, no solo los features) pero puedo plantear algunas cuestiones que para mi son importantes (mmm ya me veo escribiendo un post largo ): 1 - Oferta/Demada + Tu toque: El primer error es suponer que el precio representa el esfuerzo detras. Si esto fuera así un asset complejo saldría un ojo de la cara. Como todo, es un balance entre oferta y demanda, pero también podés meter el "factor humano" en el medio. Esto va de la mano con el punto 2 (casi el método clásico de elección en el Asset store) ---> 2 - Buscar assets similares: Esto puede ser beneficioso o no. A veces tenés que hacer la tuya y sobresalir con el precio. Basicamente le decís a quien te compra el producto "Soy mejor que el resto" (que dicho sea de paso es alguien que probablemente no tenga conocimiento del "resto"). Esto lo podés asociar a una "etiqueta" de precio (creo que así las llaman). Por ej, para el mundo de los juegos, si compras algo de $60 es un juego AAA (esto ya es como cultura general ya), entonces vos esperas un producto así. Buscá un asset similar y (como estás arrancando) cobralo (no se) 5 dolares menos ... esto va al punto 3 ---> 3 - Futuros incrementos: ¿Cual es tu plan a futuro con el precio? pensas poner el asset a un precio final de entrada? o ir incrementando poco a poco? (una o dos veces el primer año). Quizás esto pueda usarse como estrategia también. El comprador solo se da cuenta de esto, no es necesario hacer un aviso. 4 - Más allá del contenido del asset, muchas veces lo que vale (y mucho) es: 4.1 Soporte: Responder mails, resolver bugs, etc. Atención en general, ser "profesional", saludar formalmente. Basicamente transmitir al cliente y al resto que están lidiando con alguien que se preocupa por ellos, no solo alguien que junto código y lo subió a la store para ganar dinerillo. 4.2 Documentación, manuales, referencias de API, todo esto te da un colchón impresionante. Evitar word, bloc de notas, y todas esas cosas medias cutres. Es muy útil saber redactar tu documentación y además presentarla bien. 4.3 Extras de todo tipo: página web propia, demos, redes sociales, contactos, en redes sociales y en el mismo foro de Unity. 5 - Código "PRO" (al menos a la vista jaja): Esto puede o no aplicarse a tu caso, si tenés código está bueno diseñarlo usando ciertos estándares, sobretodo para extenderlo, mejorarlo vos mismo y además brindar documentación de la API. No solo algo que haga un tarea y listo. EJ: Esto mueve a un objecto 5 unidades por segundo en una dirección: Esto hace exactamente lo mismo, y además explica bien de que va cada campo y método, además de que permite personalizar el método (en esta caso una pavada) con una implementación propia haciendole un override: 6 - Metadata: A lo último pero muy importante también. Que és esto? videos, imagenes, Logos, etc. Tampoco es necesario pegar altas ediciones de video, ni ser un experto de Ilustrator, simplemente tener algo de gusto y un poco de sentido común. En resumen, te sugiero que te vayas al punto 2. Empezá a buscar asset similares. Si pensas que a futuro lo vas a dejar mejor que no te importe cobrar más incluso si a la primera no vendés nada. Tené cuidado con poner algo a un precio y bajarlo porque no se vende, esto lo que transmite es falta de confianza. Tampoco pongas un precio exageradamente bajo porque lo vas a terminar subiendo mucho seguramente. Tu asset se ve muy prometedor! La verdad que por lo técnico soy un queso diciendote vale tanto. También te diría que mantengas ese "look Unity" y no metas demasiados colores y cosas a la UI , basicamente usá estilos compatibles con Unity (Button, Box, HelpBox, etc). No hagas lo que hizo el autor de Aura2 (En las reviews lo matan con esto). Otra, andate a los UI Element si podés, este año va a ser el año del pase, más de la mitad de la gente que usa el Asset store está en 2019! (está en el foro de publishers). Y además 2020 trae (supuestamente) el nuevo Input System. Así que para nosotros que vendemos assets es un momento clave de transición. (jaja terminó el magapost y no te dije ni un valor ... ponele $15 dolares a ver que pasa , de última le subís) Saludos
  20. 2 likes
    Hola Os informo de que Vuforia se está poniendo las pilas con las licencias. Si publicáis un app que les llama la atención, no podréis usar la licencia de developer y os pedirán que paguéis por la licencia. El problema es, si habéis publicado con la de developer, no podréis comprar la standard sino la Pro que vale una pasta al año. Os recomiendo que si empezáis un proyecto de AR, os miréis y lo hagáis con el ARFoundation de Unity. Saludos
  21. 2 likes
    actualizacion del sistema. lo nombre "modelator", que piensan al respecto? dejo un video, en el cual se crear un pequeño escenario para la prueba! espero que les guste!
  22. 1 like
    Yo no pienso a los juegos por sus inputs (tal o tal mando, móvil, desktop, etc), sino por sus acciones/género (ambos muy ligados). Por ej, en un platformer 2D moverte a la derecha será apretar la flecha derecha, la D o cualquier otra tecla en PC, en android será tomar el desplazamiento de un joystick, en la switch será .. .etc etc. Es decir, tu juego requiere que el personaje se mueva a derecha, esta es la base, las inputs se deberán adaptar a esto. Una vez tengas la base del gameplay, podés darle algún "sabor" a las inputs. El ejemplo más claro es usar el joystick para desplazar lentamente al jugador. En PC no es posible ya que o apretás o no. Con un mando o desde el móvil podés regular esta acción. Dicho todo esto, ambas acciones se realizan de igual manera, el PC lo leerá de 0% o 100% y el mando de 0% a 100%, osea que no vas a hacer un juego completo en android, y otro para desktop. Habrá variaciones, sí, pero tratá de generalizar los conceptos de fondo, la "base" que mencioné antes. Esto me gusta pensarlo como un shader, los shaders a su vez tienen sub shaders, si el gpu no te tira el de mayor nivel, pasará a otro de menor nivel, y así, hasta que al final habrá un Fallback X, que significa que si nada anduvo use este X. Con las acciones hacé lo mismo, definí la base y de ahí anda maximizando la experiencia para cada dispositivo, como dijo @iRobb, siempre y cuando un dispositivo no le saque un ventaja notable a otro. Ej: En PC tenés que apuntar y disparar usando el ratón. En android tocás a quien matar en la pantalla y listo, apunta y lo mata automaticamente. Por lo general cada estilo de juegos tiene su plataforma de preferencia, los platformers van con los típicos mandos ya que necesitas acciones fáciles y conocidas. Para un RTS de alta competición probablemente un móvil o un mando no sean lo indicado. Teclado, aunque me gustaría usar un mando. Ya que está: Alguien quiere regalarme un mando? (bueno tenía que intentar) Juegos XXX Hot de plataformas (metroidvanias en general, otro género me aburre), point and click (muy fan de estos), algún que otro en primera persona, pero enfocados en la ambientación (estilo The vanishing of ethan carter, Dear esther, soma, amnesia, etc). Igual hace años que no juego a nada.
  23. 1 like
    No sé que tipo de videojuego estás creando aunque creo que en vez de intentar generalizar los controles en móvil y PC es un error. Creo que es mejor utilizar las diferencias que tienen para dar una mejor experiencia. O sea, PC con mando, que seguro se puede saber de qué tipo es, y en móvil utilizar el compass/giróscopo y algún botón virtual por ejemplo.
  24. 1 like
    Te voy a dar por orden las cosas de deberías hacer. 1 - Adaptarse a utilizar los niveles de accesos como corresponde, si no especificas que x función es privada, pública, interna, protected, esto tiene razones de seguridad, pero tambien simplifica las cosas a la hora de leer código. private void Update(){ } private void Start(){ } 2 - Adaptarse a una nomenclatura "coding convention" esto hace que sea mucho más fácil programar y leer el código, las que te recomiendo serian las siguientes. Todas las variables publicas, internas y protegidas deben empezar con mayúsculas. Todas las variables privadas deben empezar con "m_" Todos los parámetros de una función deben empezar con minúsculas. Todas las variables dentro de una función deben empezar con minúsculas (como sus parámetros). 3 - Siempre que sea posible se debería omitir el uso de GetComponent, esto quiere decir que podes guardar referencias del componente en un campo para luego ser utilizado, esta tarea siempre que sea posible se debe realizar desde la función Awake(), es muy importante esto. public class PlayerController : MonoBehaviour { public static PlayerController Instance { get; private set; } private ShootingManager m_shootingManager { get; set; } private AmmoManager m_ammoManager { get; set; } private HealthManager m_healthManager { get; set; } private void Awake() { Instance = this; m_shootingManager = GetComponent<ShootingManager>(); m_ammoManager = GetComponent<AmmoManager>(); m_healthManager = GetComponent<HealthManager>(); } } 4 - Intenta crear propiedades que agrupen cierto comportamiento lógico para evitar estar repitiendo código constantemente. private bool m_availableShot { get { return m_ammoManager.haveAmmo && m_healthManager.canShoot && PlayerController.Instance.canMove; } } 5 - Evita usar static string, es mejor declararlos dentro de una constante private const string _BUTTON_FIRE_1 = "Fire1"; Te dejo un código de ejemplo basado en lo que compartiste para que puedas evaluar y ver cómo mejorar el tuyo, no esta mal, pero está lejos de ser algo funcional. Ánimo! public class PlayerController : MonoBehaviour { public static PlayerController Instance { get; private set; } private ShootingManager m_shootingManager { get; set; } private AmmoManager m_ammoManager { get; set; } private HealthManager m_healthManager { get; set; } private void Awake() { Instance = this; m_shootingManager = GetComponent<ShootingManager>(); m_ammoManager = GetComponent<AmmoManager>(); m_healthManager = GetComponent<HealthManager>(); } } public class ShootingManager : MonoBehaviour { private const string _BUTTON_FIRE_1 = "Fire1"; public static ShootingManager Instance { get; private set; } private AmmoManager m_ammoManager { get; set; } private HealthManager m_healthManager { get; set; } [SerializeField] private BulletManager m_bulletPrefab = null; private bool m_availableShot { get { return m_ammoManager.haveAmmo && m_healthManager.canShoot && PlayerController.Instance.canMove; } } private void Awake() { Instance = this; m_ammoManager = GetComponent<AmmoManager>(); m_healthManager = GetComponent<HealthManager>(); } private void Update() { if (Input.GetButton(_BUTTON_FIRE_1) && m_availableShot) OnShoot(); } private void OnShoot() { BulletManager bullet = Instantiate(m_bulletPrefab, transform.position, transform.rotation); bullet.Initialize(); } } public class BulletManager : MonoBehaviour { [SerializeField] private float m_speed = 10; [SerializeField] private float m_lifeTime = 3; private Rigidbody2D m_rigidbody { get; set; } private void Awake() { m_rigidbody = GetComponent<Rigidbody2D>(); } internal void Initialize() { player = PlayerController.Instance; //Logica del bullet. } }
  25. 1 like
    Jaja sí, surgió como un "fork" de la versión en 2D, ya que quería una versión "todo terreno 4x4" (a.k.a 2D/3D), y ante un problema con la falta de depenetración en 2D (que en 3D funciona a la perfección) dije "y si lo hago dinámico ???" y ahí está. (de los rigidbodies dinámicos aprendí muchísimo, sobre todo de contactos y demás) Ahora estoy tratando de pasar el asset 2D (Kinematic 2D) al mundo del 3D pero manteniendolo kinemático y 2D (no se si me explico). Y así dar soporte a los dos, pensándolos como uno solo (a grandes rasgos). Para nada, todo pura fachada. off kors
  26. 1 like
    Diría que tendrías que reescalar el background negro a la resolución del dispositivo y no reescalar el panel del 1080p. El background negro sería el último gameobject de la jerarquía para que se sobreponga sobre todo el resto.
  27. 1 like
    Bueno, la mía también la utilizo profesionalmente En el mío para otros objetos de tipo multimedia como vídeos por ejemplo, se alojan en AWS en estructuras de carpetas multiidioma que son descargados dependiendo del mismo. También existe el idioma neutral, que sería un objeto no dependiente de multiidioma.
  28. 1 like
    Un campo es una variable que se declara directamente en una clase o estructura. Una clase o estructura puede tener campos de instancia o campos estáticos o ambos. En general, debe usar campos solo para variables que tengan accesibilidad privada o protegida . Los datos que su clase expone al código del cliente se deben proporcionar a través de métodos, propiedades e indexadores. Al utilizar estas construcciones para el acceso indirecto a los campos internos, puede protegerse contra valores de entrada no válidos. Ejemplo public class MiClase { public float MiCampo = 0; } Una propiedad es un miembro que proporciona un mecanismo flexible para leer, escribir o calcular el valor de un campo privado. Las propiedades se pueden usar como si fueran miembros de datos públicos, pero en realidad son métodos especiales llamados accesores . Esto permite acceder fácilmente a los datos y aún así ayuda a promover la seguridad y flexibilidad de los métodos . Las propiedades permiten que una clase exponga una forma pública de obtener y establecer valores, al tiempo que oculta el código de implementación o verificación. Se utiliza un descriptor de acceso de propiedad get para devolver el valor de la propiedad, y un descriptor de acceso set se utiliza para asignar un nuevo valor. Ejemplo public class MiClase { private float m_miPropiedadValue = 0; public float MiPropiedadBidireccional { get; set;} public float MiPropiedadUnidireccionalGET { get { return m_miPropiedadValue; } } public float MiPropiedadUnidireccionalSET { set { m_miPropiedadValue = value; } } //VALUE es el valor que se le esta asignando a una variable. } Entonces podemos decir que un campo es la forma de representar libremente una variable. Mientras que una propiedad es un forma de enmascarar un campo o valor, las propiedades tambien se pueden utilizar para realizar cálculos u otra combinación de información. Ejemplo public class PlayerStatistics { public int Defense; public int Attack; public int Velocity; public int Range { get { return (Defense + Attack + Veloctiy) / 3; } } //Desde la versión 4.7 de C# se pueden utilzar las arrow propertys //La desventaja es que solo son para propiedades de solo lectura. public int Range => (Defense + Attack + Veloctiy) / 3; } Aparte de esta explicaciones básica existe diferencias en el MSIL pero esto ya es más técnico.
  29. 1 like
    El uso de Mathf.Clamp es correcto, pero si vas a asignar la variable desde múltiples lugares te recomiendo utilizar propiedades. private float m_value = 0; public float Value { get {return m_value;} set { m_value = Mathf.Clamp(m_value, 0, 1);} } De este modo cada vez que asignes Value se va a aplicar la limitación.
  30. 1 like
    Gracias nomoregames y siento lo de tu ruptura, espero que se pueda arreglar. He puesto unas capturas de pantalla en el primer post, ahora si me ha dejado ponerlas, saludos.
  31. 1 like
    Bienvenido al mundo de los IK y los RIG... Es bastante complicado de encontrar el flujo de trabajo correcto, pero con el tiempo te vas acostumbrando a la forma de trabajar con RIG.
  32. 1 like
    Muy bien! Yo también he estado con el ARCore y el ARFoundations. Publiqué uno por aquí. Te pongo tu vídeo embebido:
  33. 1 like
    No, una cosa es un error, un fallo, algo que está puesto así que no debe ser así. Unity tiene muchos mensajes, callbacks o como los quieras llamar. Justamente, es porque queremos un engine para crear juegos que ellos ponen a disposición todos estos callbacks. Desde ya que en Unity Technologies no tienen una bola mágica para adivinar qué es lo que los millones de usuarios van a hacer, en plan de "ciclo de update para todos y todas". Quizás OnAnimatorIK resulte útil para actualizar el transform de los IK. Si tuvieras que procesar algo cada vez que un contacto ocurra será OnCollisionEnter, para otra tarea como reconocer inputs vendrá bárbaro Update, para aplicar fuerzas a un rb será FixedUpdate, y así. Como te dice Franco, dependiendo del "game loop" te resultará Start, Update, FixedUpdate, etc. Ellos simplemente destripan todo el loop y te lo dan en forma de callbacks o mensajes. Acá tenés una lista completa (bajá hasta "Messages"): ---> MonoBehaviour Todo esto está más que detallado en la documentación: Execution Order FixedUpdate FixedUpdate should be used instead of Update when dealing with Rigidbody. For example when adding a force to a rigidbody, you have to apply the force every fixed frame inside FixedUpdate instead of every frame inside Update. Bueno, creo que Franco ya lo explicó arriba. Es por el tema de la simulación física. Este concepto no es algo fácil de agarrar si recién empezas con motores en general, y eso que estamos hablando de Unity que es relativamente amigable. Para obtener resultados coherentes los motores físicos usan un "Tick" fijo, usando un fixed delta time. Con lo que mencioné arriba de autoSync, desde 2017 (creo) hacia adelante empezó el proceso de abandonar la sincronización automática entre Transform y cuerpo físico. Esto significa que si vas a tocar (en cualquier forma) a un rigidbody o collider asociado debés usar FixedUpdate , ya que estos forman parte de las físicas de motor (si es que querés hacer las cosas bien, claro que podrías reactivar autosync y fué, pero esto no es una buena práctica). Es decir, el único momento en el que el cambio tiene notoriedad es luego de que haya pasado el "update físico" (Internal physics update). Vos debés modificar los valores justo antes de este update físico. Y donde está dicho Update? bueno para tener 100% conociemiento de esto te pasé lo siguiente ---> Execution Order Fijate que OnAnimatorMove es válido, pero solo se da cuando el animator se mueve (??, ir a la doc), OnStateMachineenter/Exit es válido, y pero si no tuvieras una state machine de Animator? como vez todos estos podrían llegar a funcionar pero dependen de componentes de animación y de eventos en concreto (enter/exit,OnMove, etc). Entonces, ¿Cual de estos bloques te asegura que se ejecute una y otra vez sin depender de ningun componente? --> Fixed Update -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Estos temas no son super fáciles de agarrar a la primera. Te recomendaría crearte un proyecto separado (o escena separada) y empezar a jugar con esto. Imprimiendo en consola mensajes, dibujando rays, lo que sea que te ayude más a entender toda esta estructura (ya que es lo básico). Pero ojo, esto no significa que cualquiera que haga juegos por ahí se sepa esto al 100%, me atrevería a decir que probablemente el 40% de los que usan y crean juegos en Unity (hasta juegos comerciales) ni siquieran se saben que FixedUpdate está sobre el mismo hilo que Update. En el foro oficial ves a usuarios "pro" que dicen que Update y FixedUpdate corren de manera separada en sus mundos, como si fueran dos hilos completamente distintos (a pesar de que el diagrama de arriba está bastante bastante claro de que esto no es así). Por eso, tomate tu tiempo, esto no se aprende en 1 día.
  34. 1 like
    Te voy a contestar nuevamente intentando no herir tus sentimientos. 2 cosas importantes antes de empezar, la definición de comando está muy alejada de lo que realmente quieres expresar, en dicho caso deberias utilizar algo referente al código, por ejemplo, línea de código, API, etc. Segundo, lo que estás llamando proceso se define como Función, son cosas demasiado diferentes para confundirlas. Ahora dejando claro lo anterior vamos al tema del ¿por qué se utiliza más de una función de actualización?, el por que es simple, Unity como todos los motores gráficos que existen tienen un variable que se conoce como GameTime esta variable Unity la llama deltaTime, no es más que el tiempo que pasó desde el último frame al actual, esto nos sirve para crear una lógica consistente. EJ. si intentas trasladar un objeto sin deltaTime este dependerá de cuantos FPS tengas en el momento, sin embargo si multiplicas esto por deltaTime entonces compensaras el movimiento entre diferentes FPS, esto es una simple regla de 3 simples. ¿Por que FixedUpdate? La separación de Update y FixedUpdate se debe a una decisión de diseño y una solución a Physics Pass, mientras la función Update se llama en cada frame, la función FixedUpdate se puede llamar 1, 0, o varias veces todo depende del Physics Pass y la configuración del proyecto. Las físicas no solo hacen que tu Rigidbody se mueva, si no, tiene que calcular los Hitbox, contacts, triggers, joins y todos lo componentes físicos que existan en la escena. ¿Por qué no usar siempre FixedUpdate? Por la misma razón que no colocas la lógica del Juego dentro de la función Start o Awake, por que no se trata de la función que deriva del Game Loop. Si estás interesado en saber más te recomiendo LEER lo siguiente donde explica muy bien el ciclo de vida de un juego. https://ir.lib.uwo.ca/cgi/viewcontent.cgi?referer=&httpsredir=1&article=1138&context=electricalpub Suerte!
  35. 1 like
    Que notición @pioj, desde ya al igual que como te dicen arriba, agradecerte por todo. Yo me inicié en Unity Spain allá por el 2011 creo (solo estuve un año), y no era nada pero absolutamente nada lo que es hoy en día. Incluso el foro oficial de unity es un chiste frente a este. Así que muchas gracias por todo , lo tenés más que merecido y no cabe duda que todos aquí opinan lo mismo. Me asustó lo de " dejar el mundo del Desarrollo de Videojuegos, tal vez hasta la Informática. ", pero bueno, tendrás tus justas razones. A meterle pa' delante. @francoe1 no hay drama, contá con mi ayuda en lo que pueda. Eso sí, tené en cuenta que no es lo mismo ser activo que administrar una comunidad como esta, no lo digo por vos, lo digo por mí .
  36. 1 like
    @Pathus22 en el video de la clase 2 vi que tenés el ícono del Epic Games Launcher ... traidor! Jaja, muy buenos vids, bien desarrollados y rapiditos. En la clase 1 dijiste "bajen siempre la última version que seguramente va a estar bien para estas clases" (o similar), conociendo a Unity de 2017 a 2020 ya no tenés certeza de nada, si hiciste algo en la 2020.1 seguramente en la 2020.2 se rompe todo . Me interesa muchísimo la parte de multiplayer, así que voy a esperar. ¿Podrías subir el temario completo (más o menos)? O es spoiler? Saludos
  37. 1 like
    Hola comunidad de Unity Spain llevo ya un tiempo rondando por acá y nunca he publicado ningún proyecto este vendría siendo mi segundo proyecto, tiene el nombre de Crewild. Es un versión western del mundo de pokemon con algunas cosas que voy a implementar a futuro como un sistema de supervivencia y posturas por ahora es funcional pero esta roto el sistema de batalla y posee muchos bugs que estoy tratando de corregir en la prontitud . Apenas voy en la versión 0.0.1 publico algunas imágenes de concepción de arte mías de los escenarios que quiero crear, tengo la dificulta de que la música que poseo es muy pocas, ruego disculpen los bugs y los menús algunos todavía necesitan re diseñarse. Espero lo disfruten, comenten abajo que les pareció y que recomendaciones pueden darme, aquí una pequeña demo. https://drive.google.com/open?id=1mQWMdw9n94R6PYsDgXxEr7yefADUkEYc
  38. 1 like
    Es una pasada. cuando acabe con lo que tengo entre manos lo probare seguro.
  39. 1 like
    Buenos días, está claro que yo no se de esto ni la mitad que usted y no pretendo dármelas de listo, tan solo soy un aprendiz autodidacta de la programación con el sueño de poder realizar un juego aunque sea parecido a los triple A (porque todos los juegos que he hecho han sido proyectos sin acabar que dejan mucho que desear). Pero a veces nos complicamos mas de la cuenta para hacer cosas sencillas y desde lo poco que conozco, se que por ejemplo cuando usamos time.Deltatime tras ese comando que Unity nos facilita hay una variable que va sumando al igual que si la creamos nosotros y que si usamos time.Deltatime 40 veces, cada vez es un contador nuevo que ha creado Unity, por tanto una variable invisible que nos consume recursos. Muchas veces hacemos las cosas mas complicadas de lo que son por querer hacerlas perfectas. Mi lema es: si funciona, hazlo. Un saludo.
  40. 1 like
    para solucionarlo bien bien tendria que tener mucha mas informacion.... cual es el eje que mira hacia adelante en la cabeza.... porque si dices que estan mal los ejes signnifica que el Z no apunta hacia adelante... y entonces seguro que el Y no apunta hacia arriba y el X no apunta hacia la derecha.... porque lo suyo seria hacerlo usando los ejes y calcular cuanto tiene que rotar con respecto a como esta rotada "dentro" de la animacion... porque la animacion supongo que movera un poco la cabeza (suavemente).. lo suyo seria calcular el angulo usando los vectores de direccion de la cabeza... usando Vector3.Dot para obtener seno y coseno del angulo que forma la cabeza respecto al vector al que llamas "Direccion_Cabeza"(*)... y luego usar Mathf.ATan2 para hayar el angulo que debes girar. si me das los ejes, si me dices hacia donde apuntan los ejes x,y,z de la cabeza puedo intentar hacertelo, ...pero al final no se si funcionara bien... lo suyo seria que pudiera acceder a tu proyecto y asi te lo podria "arreglar" en un momento... unas unityCloud? tienes el proyecto en la "nube" de unity? si quieres te paso mi correo para que me des acceso (momentaneo) a tu proyecto y le hecho un ojo... aunque este finde me pilla un poco mal... estare viernes, sabado y domingo fuera... pero el lunes te lo puedo mirar si quieres (*) las variables deberian comenzar con minusculas ("direccion_Cabeza") y las "classes" y funciones en Mayuscula.
  41. 1 like
    hola puedes usar el transform.LookAt y luego rotarlo manualmene para corregir con transform.Rotate(x,y,z) por ejemplo pongamos que al rotarlo con LookAt la cabeza queda ladeada 90 en el eje Z pues luego le pones un Rotate(0, 0, -90) y solucionado.... o si queda mirando hacia arriba le pones un Rotate(90, 0, 0)... (pero despues del LookAt) espero que te sirva. sino, hay otras formas de hacerlo, puedes poner un objeto vacio (empty gameobject) dentro de la cabeza y que ese si este orientado correctamente, calculas el vector3 "normalizado" desde ese objeto al punto donde debe mirar, y con vector3.dot entre ese vector y los vectores forward y right puedes calcular el seno y coseno de los angulo Y que forma, ...y con el vector y forward y up puedes calcular seno y coseno del angulo X... sabiendo los senos y cosenos puedes usar Mathf.ATan2 para saber el angulo y luego los usas en el eje apropiado con Rotate, rotando porejemplo el eje "Y" con el angulo "X" y el eje "Z" con el angulo "Y"... o lo que sea... y aun hay mas maneras de solucionarlo.. porejemplo rotas la cabeza con LookAt, guardas los valores del transform.eulerAngles en un vector3 "angulosCabeza" y luego intercambias los valores de X por Y o lo que sea... osea pones los eulerAngles en otro orden... en vez de x,y,z luego le metes los valores en otro orden... z,x,y o lo que sea... aunque creo que hacer esto fallara porque primero tendrias que hayar el angulo entre el cuerpo y la cabeza (anguloY cabeza menos anguloY cuerpo) y eso son los valores que luego tendrias que intercambiar... y seguro que hay mas formas... si no te funciona ninguna de estas puedo pensar otra... o si no logras hacer una de las que te he puesto (ya que lo he explicado a lo rapido) puedo intentar explicarlo mejor... o tambien si quieres te pongo ejemplos con codigo
  42. 1 like
    @Jhonatan00_00 pudiste solucionar tu problema?
  43. 1 like
    hola, acabo de hacer esto probando using System.Collections; using System.Collections.Generic; using UnityEngine; public class playerGalaxy : MonoBehaviour { private float camAngleX = 0; private float camAngleY = 0; private float sensitivity = 10f; private float speed = 10; private float gravy = 0; private float gravyPower = 8.8f; public Transform cam; //camera private Vector3 oldPos = Vector3.zero; private Vector3 move = Vector3.zero; // Use this for initialization void Start () { } // Update is called once per frame void Update () { float dTime = Time.deltaTime; //look camAngleY *= 0.8f; camAngleY += (Input.GetAxis("Mouse X")) * sensitivity * dTime; camAngleX -= (Input.GetAxis("Mouse Y")) * sensitivity * dTime; camAngleX = Mathf.Clamp(camAngleX, -80f, 80f); cam.position = oldPos + (transform.up * 0.6f); transform.Rotate(0, camAngleY, 0); cam.rotation = transform.rotation; cam.Rotate(camAngleX, 0, 0); cam.position -= cam.forward * 5f; //move oldPos = transform.position; float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); Vector3 mov = new Vector3(h, 0, v); if (mov.magnitude > 1) { mov.Normalize(); } move = Vector3.Lerp(move, mov, 0.1f); Vector3 moveDir = ((move.x * transform.right) + (move.z * transform.forward)) * speed * dTime; //transform.position += moveDir; //physics Vector3 newUp = Vector3.zero; RaycastHit hit; float radius = 0.4f; bool inGround = false; //forward (move dir) if (Physics.SphereCast(transform.position, radius, moveDir.normalized, out hit, moveDir.magnitude+0.01f)) { transform.position += moveDir.normalized * hit.distance; //newUp = hit.normal; } else { transform.position += moveDir; } //down if (gravy > 0) {//falling if (Physics.SphereCast(transform.position, radius, -transform.up, out hit, (gravy * dTime) + 0.3f)) { transform.position -= transform.up * (hit.distance-0.1f); newUp = hit.normal; gravy = 0; inGround = true; } else { transform.position -= transform.up * gravy * dTime; } } else {//jumping if (Physics.SphereCast(transform.position, radius, transform.up, out hit, -((gravy * dTime) + 0.2f))) { transform.position += transform.up * hit.distance; //newUp = hit.normal; gravy = 0; } else { transform.position -= transform.up * gravy * dTime; } } if (inGround) { if (Input.GetButtonDown("Fire1") || Input.GetButtonDown("Jump")) { gravy = -7f;//jump } } gravy += gravyPower * dTime; //rotation if (newUp.magnitude > 0.1f) { Vector3 left = Vector3.Cross(transform.forward, newUp); Vector3 newForward = Vector3.Cross(newUp, left); Quaternion oldRot = transform.rotation; Quaternion newRot = Quaternion.LookRotation(newForward, newUp); transform.rotation = Quaternion.Lerp(oldRot, newRot, 0.15f); } } } es andar por las paredes al estilo mario galaxy. en tercera persona. lo he provado con una Sphere de tamaño 1 (la que sale por defecto) poniendole un rigidBody al que le he desactivado la gravedad y le he "freezeado" los tres angulos de rotacion (los tres "freeze rotation") tiene algun problema como que caes hacia abajo (del transform) en vez de hacia al "suelo" mas cercano... habria que ponerle un "Physics.OverlapSphere" que fuera creciendo para buscar el "suelo" mas cercano cuando estas en el aire... ya le pondre luego, ahora me tengo que ir a hacer unos recados... espero que te sirva... luego (o mañana) ya lo mejorare... lo he hecho en 5 minutos... y tiene "fallos"
  44. 1 like
    En general no existen reglas, podés hacer lo que quieras, todo dependerá del tipo de resultado deseado. "Si se mueve y te gusta el resultado, está bien" - Lightbug, enero de 2020. Por ejemplo: asignando la velocidad de manera absoluta te da algo super exacto, basicamente querés que el cuerpo vaya a tal lugar y lo tenés. Todavía tenés alguna que otra cosita que te puede modificar el comportamiento (drag, angular drag, materiales físicos, etc) pero tenés trucos para todo esto. Si por el contrario querés que la simulación sea 100% real life no fake entonces asignar la velocidad de manera absoluta (lo remarco de nuevo) es lo peor que podés hacer. En este mundo tenés similaridades con el cálculo diferencial. Disponés de "órdenes de control" sobre la posición y rotación: orden 0: (sin derivar): Posición y rotación -> basicamente personajes kinemáticos order 1: (derivando lo anterior) -> velocidad lineal y velocidad angular -> rigidbodies dinámicos orden 2: (resultado de derivando lo anterior) -> Fuerza y Torque. -> rigidbodies dinámicos Mientras mayor es el orden tenés menor control. Notá que para el orden 2 no podés anular la velocidad de golpe, vas a obtener un resultado más realista (no necesariamente un mejor resultado). ──────────────────────────────────────────────────────────────────────────── Por ej para el orden 2 es muy útil utilizar controladores PID para realizar movimientos algo precisos empleando fuerzas. En resumen, tenés una entrada de referencia con velocidad = v (puede ser cualquier valor), esta señal pasa por unos bloques de compensación (el PID) luego la velocidad de salida se realimenta a la entrada y se calcula la diferencia entre este resultado y la velocidad de set v. Esto finalmente reingresa al loop y así forever. La velocidad de salida tenderá al valor de set, esto por las características del PID, también dependerá mucho de la elección de los parámetros Kp Ki y Kd. Aca un vid con un ejemplo de posición: Todo esto es teoría de control, el tema es bastante complejo como para entenderlo en un post. Hay mucho material muy interesante.
  45. 1 like
    Buenas, gente!! Quería haceros una pregunta. Tengo mi juego listo, y llevo usando Steam una temporada para probar que todo va bien con testers y tal. El caso es que en cree dos repositorios para estas betas, una donde subía el proyecto ejecutable (Windows) y otra donde subía el proyecto de tipo .app (Mac). Ahora quiero subir el juego al repositorio bueno, es decir, al repositorio definitivo, para que Steam evalue el juego y lo ponga a la venta. Mi duda es la siguiente, ¿cómo hago para meterle al mismo el juego tanto en windows como en mac? ¿O es que tengo que crear varios repositorios y, de alguna manera, chequearlos como el bueno? Espero vuestro sabio consejo, pues por mucho que busco no encuentro respuestas a esta pregunta. Gracias de antemano.
  46. 1 like
    la bala da dolor de cabeza.... si le disparas en la cabeza? y si disparas a la pierna da cojera? jeje ahora en serio: seguramente es que la variable "player" que "buscas" en la funcion "Start", despues del cambio de "tag" es "null", osea, que la funcion "FindGameObjectaWithTag no encuentra el objeto en cuestion. asegurate que despues del respawn el player recupera su tag correctamente. puedes poner esto despues del FindGameObjectWithTag para ver si el gameObject es "null" if (player == null) { Debug.Log("objeto nulo"); } si sale el mensaje en la consola significa que el objeto no ha sido encontrado, y segurente es por el cambio de tag
  47. 1 like
    Hola! Es una manera brusca pero tal vez te sirva: El "1f" cambialo por "step" ya que este se va a actualizar en cada frame hasta llegar a 1. public float time; //Juega con este valor para ver los resultados. void Retroceso() { punto_inicial = new Vector3(camara.transform.localEulerAngles.x,camara.transform.localEulerAngles.y); camara.transform.localEulerAngles = new Vector3(camara.transform.localEulerAngles.x - 4f, camara.transform.localEulerAngles.y); // esto es el retroceso en si } StartCoroutine(ActualizaElEstado(Vector3 punto_inicial, float time)); } private IEnumerator ActualizaElEstado(Vector3 punto_inicial, float time) { float inversedTime = 1 / time ; // Puedes cambiar este valor. for( step = 0.0f; step < 1.0f ; step += Time.deltaTime * inversedTime ) { camara.transform.localEulerAngles = Vector3.Lerp(camara.transform.localEulerAngles,punto_inicial, step); yield return WaitForEndOfFrame(); } }
  48. 1 like
    Cortisimo vídeo de 6 minutos, en el que usando post processing intento conseguir un Ambiente de Sueño o pesadilla para un sencillo y oscuro juego 2D.
  49. 1 like
    Os dejo mi ultimo juego por aquí a ver si le dais una oportunidad y lo probais, y me decis si os ha gustado. Es un juego 2d de plataformas creado con unity3d estilo retro y muy dificil. Descarga: https://drive.google.com/file/d/1W-M7m3-0p2eVcJzxiHaWeJamtzy-_lGq/view?usp=sharing
  50. 1 like
    Buenas gente, He subido la nueva versión BETA V3, en principio va a ser la definitiva. He realizado las siguientes modificaciones y mejoras: -Rediseño UI -Mejora en la escena del baño principal. La he potenciado un poco con efectos visuales. -Mejora de la escena final. -He añadido algún "susto" más. -Cambio de algunos sonidos, como en el sótano que he cambiado el sonido de las pisadas en el agua, antes sonaban a lata y muy cutres. -He añadido un "huevo de pascua". ¿a ver si lo descubrís? -He cambiado algunas texturas. -remodelado algunos objetos como el reloj de cuco del altillo. -Optimizado un poco más. -Añadida la funcionalidad de agarrar algunos objetos gracias al script que dejo amablemente lightbug ;). Os dejo algunas imágenes con algunos cambios: Aquí os dejo parte de lo que pasa si descubris el huevo de pascua.... Aquí algunos cambios de texturas en la escena final, no he puesto más por no hacer spoiler... El nuevo diseño de la UI, más sencillo para mi gusto queda mejor Imagen de la cocina con la luz en modo linear, la verdad que ha ganado bastante He añadido efectos en la escena del baño para potenciarla Probadolo a ver que os parece, he dejado el enlace arriba en la primera pagina del post. saludos¡¡
×
×
  • Create New...