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 12/27/2019 in all areas

  1. 4 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
    Acá les dejo el twitter de este señor: https://twitter.com/tuxedolabs?lang=es Sus videos y artículos son muy buenos, 100% recomendado. Tiene proyectos que integran: Geometría compleja basada en mini voxels (más tirando a átomos que al cubo de minecraft). Físicas rígidas, blandas, flexibles y de flotabilidad. Partículas, Iluminación completamente dinámica. Destrucción. Audio (para manejar todo el tema de las físicas + destrucción). Shaders. Efectos volumétricos. y más :) ... Realmente impresionante, se me hace que este tipo va a quebrar la internet en unos años. Les dejo algunos tweets: El juego que está creando (muy linda idea): Esas partículas :P
  3. 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.
  4. 3 likes
    He estado experimentando con los túneles y puentes. En realidad tendré que reescribir varias partes para poder mejorar esto, pero me ha servido para ver la problemática..
  5. 2 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
  6. 2 likes
    ¡Buenas! Este finde avancé un poco en mi experimento de carreras en TuCiudadTM. La idea es poder generar una escena aproximada de cualquier parte del mundo, y lo que hago aquí es generar la geometría desde OpenStreetMaps. Ésta es la primera prueba: La gracia, se supone, sería poder correr por tu ciudad, o hacer misiones que te envíen a sitios conocidos. Si hay algún vigués, quizá pueda reconocer la zona centro (alameda, arenal...)
  7. 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
  8. 2 likes
    Bueno, es un poco chorra el aporte, pero ahí va. Se trate de como imprimir por consola solo la parte entera de una variable decimal, o solo los decimales deseados. Lo he hecho de dos maneras, primero con un casteo a int y luego con ToString("F"), creo que tambien se puede hacer con Math, pero eso no lo he probado, en fin, si alguien quiere aportar algo más, genial: https://www.youtube.com/watch?v=nUOfEiP1iZI Saluti
  9. 2 likes
    El "efecto" que estas buscando es el mismo que el de Super Mario 64, lamento comentarte que existen múltiples problemas matemáticos a solventar, primero vamos a diferenciar los dos tipos.. La dirección del jugador en el eje FORWARD es relativa a la camara. La dirección del jugador en el efe FORWARD es absoluta a la camara. En la forma (1) vas a tener que ver la diferencia angular absoluta sobre el eje Y entre la cámara y el jugador. float diff = Mathf.Abs(cam.angle.y - player.angle.y); Teniendo la diferencia puedes crear el comportamiento necesario para compensar la rotación con el movimiento. player.angle.y = Mathf.Lerp(player.angle.y, cam.angle.y, lerp_time); if (diff < 2) MovePlayer(); Esta explicación es la que te dimos anteriormente, a diferencia que se intenta crear un valor "factor" para que la rotación no sea constante. En la forma (2) vas a tener que ver la diferencia angular absoluta sobre el eje Y entre la cámara y el "Joystick Target" - ¿Que es "Joystick target"? Esto es un Vector que predice la posición futura del jugador en función al valor del joystick y la posición actual. Vector3 joystickTarget = player.position + joystick.axis; ¡Importante! - los AXIS del Joystick siempre se deben normalizar, para evitar una velocidad 1.5 en los movimientos diagonales. Ahora deberias tomar la diferencia angular entre el FORWARD del player y el valor de joystickTarget. Vector3 angle_joystick = (josytickTarget - player.position).normalized; Vector3 angle_diff = angle_joystick - player.forward; Y a partir de acá se vuelve a repetir los pasos para la forma (1). Esto no soluciona el problema al 100% en Super Mario 64 la cámara se "AUTO AJUSTA" detrás del jugador mientras este se mueve, por lo cual faltaría la implementación de la compensación de la cámara. ¿Los saltitos de rigidbody solo son perceptibles en la ventana "GAME" o tambien se ven dentro de "INSPECTOR"? Debería de sacarte esta duda por que podria ser un error en el comportamiento de seguimiento de la cámara, tal como para las físicas se utiliza FixedUpdate para la actualización de la posición y rotación de la cámara se recomienda utilizar LateUpdate. Los códigos no funcionan son solo ejemplos.
  10. 2 likes
    Hola, Tengo un juego en beta para android y me gustaría que lo testearais por aquí los que os animéis antes de hacerlo público en la play store. Es un juego clásico en el que con una bolita hay que romper todos los bloques. Todavía hay pocos niveles (29) pero mi idea es hacer unos 150 y ya publicarlo. Os dejo el enlace donde podéis descargarlo como testers: https://play.google.com/apps/testing/com.CheviGamesSL.Reflectify También me gustaría saber por qué los anuncios(admob) reales no se ven si poniendo los id de prueba si, he leido que con anuncios reales necesitas unas cuantas solicitudes antes de que se empiecen a ver. ¿Sabéis si esto es verdad? Muchas gracias comunidad :) Preview del juego:
  11. 2 likes
    Fijaos lo que se le ha ocurrido a este hombre, "brain explode" Jaja
  12. 2 likes
    hola. este seria el mismo shader pero con bumpMap: Shader "Custom/specularTexture" { Properties{ _Color("Color", Color) = (1,1,1,1) _MainTex("Albedo (RGB)", 2D) = "white" {} _BumpMap("Bump Map", 2D) = "bump" {} _SpecColor("Specular Color", Color) = (0.5, 0.5, 0.5, 1) _SpecMap("Specular ", 2D) = "white" {} _Shininess("Shininess", Range(0.01, 1)) = 0.25 } SubShader{ Tags{ "RenderType" = "Opaque" } LOD 200 CGPROGRAM #pragma surface surf BlinnPhong #pragma target 3.0 sampler2D _MainTex; sampler2D _BumpMap; sampler2D _SpecMap; fixed4 _Color; half _Shininess; struct Input { float2 uv_MainTex; float2 uv_BumpMap; float2 uv_SpecMap; }; void surf(Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; fixed4 specTex = tex2D(_SpecMap, IN.uv_SpecMap); o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); o.Gloss = specTex.r; o.Specular = _Shininess * (specTex.r + 0.001); } ENDCG } FallBack "Diffuse" }
  13. 2 likes
    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.
  14. 2 likes
    si que puedes descargarlos de algun lado, los shaders de unity, porejemplo estan en github: https://github.com/TwoTailsGames/Unity-Built-in-Shaders pero no se si te serviran para esa version antigua que tienes de unity. pero puedes escribir tus propios shaders, en la pestaña del proyecto, de la misma forma que creas un nuevo material, puedes darle a "create/shader" (surface shader) te he escrito uno que hace justo lo que pides. crea un shader (create/shader) y llama al nuevo shader "specularTexture", abrelo con el editor/MonoDebelop/VisualStudio/blockDeNotas o como quieras borra todo lo que pone y copia esto dentro, arrastra el shader al material o seleciona en el material el nuevo shader "custom/specularTexture" ...y listo Shader "Custom/specularTexture" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _SpecColor("Specular Color", Color) = (0.5, 0.5, 0.5, 1) _SpecMap("Specular ", 2D) = "white" {} _Shininess("Shininess", Range(0.01, 1)) = 0.25 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf BlinnPhong #pragma target 3.0 sampler2D _MainTex; sampler2D _SpecMap; struct Input { float2 uv_MainTex; float2 uv_SpecMap; }; fixed4 _Color; half _Shininess; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; fixed4 specTex = tex2D(_SpecMap, IN.uv_SpecMap); o.Gloss = specTex.r; o.Specular = _Shininess * (specTex.r+0.001); } ENDCG } FallBack "Diffuse" }
  15. 2 likes
    Jajaj ya es todo una joda. A eso que dije no le des mucha bola, sería algo así: los circulos rojos (los colliders) no se tocan, pero la suma de los contactOffsets de los circulos es menor que la distancia "d". Con una layermask podés ser selectivo a la hora de hacer un cast, es decir, tenes en cuenta ciertas layers y otras no. El ejemplo más claro es en un shooter, en la escena tenés triggers que activan ciertas cosas, health packs y enemigos, ponele (además de otras cosas). Cuando disparás no querés que el raycast que usas tome en cuenta al health pack o al trigger. Entonces, en el campo LayerMask sacás "Triggers" y "Health Pack" (suponiendo que fueron previamente asignados a estas capas).
  16. 2 likes
    Para sumar a lo ya muy bien explicado por los compañeros. == significa que la expresión es "true" si el miembro izquierdo es igual que el derecho (false caso contrario). != significa lo opuesto. Viéndolo así podés convertir cosas como estas: if( golesEquipoLocal == golesEquipoVisitante ) empataron = true; else empataron = false; En algo así: empataron = golesEquipoLocal == golesEquipoVisitante;
  17. 1 like
    Está en el post de más arriba. FixedUpdate, por las razones que mencioné antes. Velocidad = Δ desplazamiento / Δ tiempo Δ desplazamiento es la cantidad de desplazamiento que le tenés que agregar a tu objeto, es decir sería tu " + transform.forward * Velocidad * Time.deltatime ": Despejando: Δ desplazamiento = Velocidad * Δ tiempo De ahí sale la forma esta (que se llama de "Euler"). Todo en realidad parte desde las derivadas, pero acá te manejas con pequeños incrementos, osea el tiempo de frame a frame (no el frame count). En el mundo Unity sería: Δ desplazamiento = Velocidad * dt Y cual es el dt que debés usar? bueno, eso depende (y no tanto, ahora vas a ver) del método que uses: Si es Update Time.deltaTime te da el tiempo que tardó el último frame. Si es FixedUpdate (<--- es este) Time.fixedDeltaTime te da el tiempo que pasó en FIxedUpdates (generalmente coincide con "Project Settings/Time/Fixed step" (creo)) Pero, y si estás en FixedUpdate y llamás a Time.deltaTIme ¿que pasa?, nada, te devuelve lo mismo que Time.fixedDeltaTime ... yo siempre uso Time.deltaTime para todo y listo. frameCount devuelte la cantidad de frames que pasaron, osea que no es un dt, no sirve. Eso habría que ver el código, osea con "tener dos fuerzas programadas" no se entiende demasiado. Lo que sí se sabe es que se debe hacer una sola llamada a MovePosition por frame físico. --> https://docs.unity3d.com/ScriptReference/Rigidbody2D.MovePosition.html It is important to understand that the actual position change will only occur during the next physics update therefore calling this method repeatedly without waiting for the next physics update will result in the last call being used. For this reason, it is recommended that it is called during the FixedUpdate callback. Note: MovePosition is intended for use with kinematic rigidbodies.
  18. 1 like
    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
  19. 1 like
    Ahora estoy ocupado y no puedo ver el código muy bien pero, creo que es porque tu script se ejecuta en start (Eso del player =...) Y como dices, tu jugador cambia de tag, puede que este dando el error porque al iniciar el void Start la supuesta linea de "player =.." queda nula porque aún no se a encontrado al "Player". Te recomiendo omitir eso de cambiar el tag en tu script, si estas usando colliders y tienes algo como esto: if (collision = GameObject.tag("Player")) { *Codigo.......* } //Agrega un Else para que no te aviente el error de los enemigos en la consola. else { //Si esta parte está vacía, no te saldrá un error. //Puedes usar un: Debug.Log("no encuentro al jugador"); //Para que te salte el mensaje en la consola } Como te digo, no puedo darte un respuesta clara ahora, pero tu error puede ser por lo del tag.
  20. 1 like
    WIP. (8/12/19) español: Hola gente! estoy desarrollando un sistema procedural, para la creación de edificios de polígonos bajos. actualmente el sistema cuenta con: - creación de estilos nuevos. - opción para agregar o quitar guías de puntos y lineas. - selección de estilos para dibujar. - menú interactivo de muestra para los estilos creados. - selección de texturas para las paredes y el tejado. - modificación de texturas (escala y posicion). - altura base del modelo. - altura total del modelo. - generar o borrar el tejado. - creación, eliminación y manipulación de nodos. - menú interactivo para crear o eliminar el estilo seleccionado, y eliminar el modelo actual en el que estas dibujando. en manos de un buen diseñador, esta podría ser una gran herramienta! ¿que opinan al respecto? espero que les guste esta idea! https://www.youtube.com/watch?v=RnpPpRkUDpk
  21. 1 like
    No usarías corrutinas para esto, porque Unity está orientado a que este tipo de lógica no necesite corrutinas: en cada frame, tienes un evento Update() para ocuparte de la lógica que necesites ejecutar. Podríamos hacerlo en una corrutina, claro, pero sería más lioso que como te ha dicho @francoe1. Una corrutina la usas cuando precisamente quieres ejecutar instrucciones a lo largo de varios frames. Por ejemplo, las uso mucho para demorar algo o secuenciar cosas (ejemplo: termina una partida, emito un sonido, paro reloj y controles, espero 2 segundos, y muestro un mensaje de Final. Para esperar esos dos segundos, podríamos usar una variable y en el Update comprobar si han pasado esos 2 segundos, pero sería engorroso hacer eso para cada secuencia, y rompe la linealidad del código. En ese caso, yo suelo hacer algo como: void Update() { if (finished) { gameStopped = true; // ejemplo: marcamos el juego como parado StartCoroutine(EndGameCoroutine); // arrancamos nuestra secuencia de fin de juego } } private IEnumerator EndGameCoroutine(float waitTime) { endSound.Play(); // ejemplo: sonido de fin de juego timer.Stop(); // ejemplo: en este ejemplo, paro el reloj del juego ya mismo ya que ha acabado la partida yield return new WaitForSeconds(2.0f); // esperamos un rato, me gusta que el jugador contemple su éxito o fracaso endGameBanner.SetActive(true); // ejemplo: mostramos un mensaje de fin de partida yield return new WaitForSeconds(3.0f); // esperamos un rato, para que el jugador pueda ver el mensaje anterior restartRound(); // ejemplo: y reiniciamos } Ves que en este ejemplo sería engorroso tener condiciones el Update() para cada una de esas esperas de 2 segundos, en cambio con una corrutina se expresa de forma secuencial. En todo momento, puede haber una o más corutinas ejecutándose. Éstas se ejecutan durante el Update(), de forma que puedes ir arrancándolas y se ejecutarán concurrentemente (en "paralelo") al resto de tus updates. Ojo a no dejar corrutinas perdidas. Fíjate también que en realidad las corutinas pendientes se ejecutan en realidad, en orden, al final del Update de la escena (no corren en hilos, sino que utilizan un modelo de programación asíncrona y de ahí que se llamen corrutinas). En resumen si lanzas una corutina en Update(), ésta se ejecutará al final del Update de ese frame para todos los objetos. Si una corrutina está esperando 2 segundos, se ejecutará la línea siguiente al final del Update cuando terminen esos 2 segundos. La manera que tiene una corrutina de "parar y esperar a algún evento" es declarándose como IEnumerator y usando ese "yield return". Esto es una peculiaridad del lenguaje y no vamos a entrar en detalles por ahora. Las corrutinas son útiles para muchas más cosas que temporizar algo. Por ejemplo, para díalogos de tipo "Aceptar / Cancelar". El código que espera la respuesta usa: bool confirmed = yield return new ShowConfirmationDialog("Are you sure?"); // esta función no es estándar, es un ejemplo Y se queda por tanto esperando a que el usuario responda a ese mensaje (es posible decirle a una corutina que "ya ha llegado su evento"). También se usan para peticiones de red o cargas de recursos (que se ejecutan por detrás, de forma asíncronas). Mi consejo es que pienses por ahora en corrutinas para secuencias de acciones programadas. Por ejemplo, al soltar tu arco, podrías querer una corrutina para: Bloquear el movimiento del jugador Sonido de disparo Preparar la flecha y lanzarla (ESPERAR) al impacto de la flecha y/o timeout <- este sería el motivo de usar una corrutina para esto comprobar el impacto (terreno válido, etc) y salir si es inválido sonido de "enganchar la flecha" crear el puente reestablecer el movimiento del jugador Igualmente, podrías hacer esto usando varios scripts en la flecha. Usar una corrutina para este tipo de secuencias depende del contexto, y de tus preferencias y estilo personal. Pero de todas formas, esto sería una vez se decide soltar la flecha... en general para gestionar los controles yo te recomiendo que no pienses en corrutinas. Igual alguien tiene otra opinión, pero yo no veo su utilidad aquí, ya que el mecanismo de Update() está pensado exactamente para esa parte de la lógica -controles, movimientos de objetos, lógica que se ejecuta en cada frame...-). En otro orden de cosas: Normalizar no es hacer que algo valga "-1, 0, o 1". Normalizar significa "regularizar" algo y normalmente a lo que nos referimos depende del contexto. Pero para empezar, es habitual referirse a valores entre -1.0 y 1.0 (con todos los números reales intermedios). Quizá en algún contexto normalizar se refiera a "-1, 0 o 1" (valores enteros discretos) pero no en este caso. En otros casos nos referimos a valores positivos entre 0 y 1 , como en este caso, donde el tiempo de tensión puede ser "0" o "máximo" pero no puede ser negativo evidentemente. Si lo normalizamos, en general, la mayoría entendemos ponerlo entre 0 y 1 (es decir, dividir por el máximo). En mi ejemplo, además lo clampeo porque si el usuario deja el ratón pulsado más tiempo entiendo que consideramos que está en el "máximo", por eso lo clampeo entre 0 y 1 (una vez dividido por el máximo: es decir, "normalizado"). Por supuesto, podrías clampear entre [0, maxTime] y luego dividir, o dividir primero y clampear entre [0, 1]... esto ya tienes que tener tú claro qué unidades y qué representa cada una de tus variables. Y yo por eso sugiero contar tiempo, y hacer las cuentas al final: así tienes siempre el dato inequívoco (tiempo pulsado) y luego con un par de cuentas (como una división y un clamp) ya lo tienes entre 0 y 1 (disparar flojísimo - máxima tensión). Al estar normalizado, lo puedes usar para multiplicar por tu fuerza, para tu animación... entre 0 y 1. Por eso todo el mundo te aconseja que intentes trabajar así y no con valores absolutos, porque luego cualquier cambio te obligará a cambiar varias cosas. Pero... ¡todos metemos constantes en el código durante las pruebas!. ...en estadística, normalizar se refiere a normalizar los valores de una serie respecto a unos parámetros estadísticos. En álgebra lineal, normalizar un vector significa hacer que su magnitud sea 1 conservando su dirección (en Unity: Vector3.normalize() y muchas otras funciones), normalizar una matriz es hacer que la transformación que representa no escale el espacio, y etc etc...
  22. 1 like
    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!
  23. 1 like
    Para esta práctica necesitas 2 "eventos", MouseUp y MouseDown. private void Update() { if (Input.GetMouseButton(0)) // Si fuera DOWN se ejecutaria 1 vez. De esta menera detecta si el mouse esta siendo presionado. { } if (Input.GetMouseButtonUp(0)) { } } Teniendo esto ahora necesitarás un factor, número del 0 al 1 que será utilizado para multiplicar el valor máximo que desees. Para esto la forma más simple y de alguna manera "segura" es utilizando Time.deltaTime para incrementar una variable. Dentro de el bloque IF del mouse "DOWN". time_amount += Time.deltaTime; Dentro de el bloque IF del mouse UP OnFinishEvent(time_amount); time_amount = 0; La función OnFinishEvent es donde ejecutaras la mecanica necesario, multiplicando time_amount normalizado * el maximo valor permitido.
  24. 1 like
    No, debería ir todo super fluido. Cómo es que estás moviendo el objeto?, necesitamos código para poder contestarte con certeza, sobretodo con estos temas que son extremadamente delicados. Siempre ojo con una alpha. Dicho esto, te tiro algunos datos sueltos que quizás te ayuden a entender un poco más este mundo. Dos mundos: Transform: transform.position, transform.Translate, transform.Rotate , etc... Físicas: rb.position, rb.MovePosition(...), rb.velocity, rb.AddForce( .. ) , etc ... Nunca nunca nunca mezclar estos mundos, por ej teniendo un Rb dinámico y moverlo usarlo Transflate. Existen casos y casos, en general no es recomendado. Yo me manejo 100% con rigibody en FixedUpdate, para mi Transform se usa para leer cosas muy específicas, o para cuestiones de Gizmos y demás, para el resto lo elimino de mis scripts (por lo menos los evito si necesito un comportamiento físico). Funcionamiento de las físicas (muy por arriba): El truco está en entender cuando las físicas hacen lo suyo y qué es lo que hacen. Basicamente cuando se da un step de simulación se realizan dos cosas (muy resumido): los physics queries (raycast, spherecast, etc) se determinan las velocidades de los rigidbodies en base a choques, materiales, etc. Una vez que esto termina se hace un "Sync", esto basicamente actualiza el componente Transform (RB -> T), que determinara visualmente donde estará el objecto. Gracias a esto es que sin tocar el Transform vos podés ver los resultados en pantalla. Que dicho sea de paso, el motor lee el componente Transform para mostrar las cosas en pantalla, todo lo visual está directamente relacionado a este (las físicas pueden recalcular todo de arriba a abajo y nada se va a actualizar en pantalla). AutoSync: Si tu objeto es kinematico y lo movés usando Transform es probable que para versiones viejas de Unity no hayas notado la diferencia con moverlo "legalmente" usando físicas. Probablemente todo haya resultado fluido, esto es porque antes se usaba "autoSync" por defecto. Este autoSync lo que hacía era detectar un cambio en un transform y recalcular toda la parte de las físicas, actualizando el Collider, la pos y rot del rigidbody. Osea que estaba todo perfectamente sincronizado (T -> RB). Desde ya que esto demandaba mayor procesamiento. Hoy en día este autoSync está desactivado por defecto, demandando mayor preocupación por parte del programador a la hora de mover un rigidbody, o de realizar simples queries. Interpolación: Un poco más complicado de entender, pero similar a lo anterior. Por qué usar interpolación? si movés un rigidbody usando FixedUpdate (como debe de ser) vas a notar que los cambios pasan a 50 fps por defecto (probablemente no tan notable,). Si esta tasa de refresco fuera cada vez menor los cambios se harían más y más notables. Como se soluciona? interpolando estos valores, ya que el Transform está más al pedo que bocina de avión, se lo usa para generar visualmente (recordar lo que dije más arriba) un resultado, mientras las físicas laburan. En el mundo transform se van a generar posiciones y/o rotaciones intermedias, es decir, va a interpolar las pos y rots para generar visualmente un resultado.Con velocity pasa lo mismo si tenés interpolación activada. MovePosition sirve si tenés un RB Kinemático con interpolación activada. Un dato extra: Si llamás a MovePosition estando en la pos A, y le decís "movete a B" ( rb.MovePosition(posB) ), vas a notar que la rb.position no se actualiza para nada (es igual a posA). Esto es porque MovePosition se actualiza después del step físico. FixedUpdate: El step físico (que hace todo lo de arriba y más) ocurre después de cada FixedUpdate, entonces si vas a mover algo usando físicas (ya sea un Rb dinámico o kinemático) lo lógico es hacerlo en FixedUpdate y no en Update. Espero que sirva de algo, quizás estás metiendo la pata en alguno de esos puntos, o quizás en alguno que no mencioné. De todos modos sería útil si subieras el código que utilizas. Saludos
  25. 1 like
    El cast a int lo va a redondear (alto o bajo, es igual) y no es lo mismo que eliminar decimales. Lo más recomendable desde mi punto de vista es String.Format de toda la vida y de otros lenguajes.
  26. 1 like
    Destrucción combinada con buenos gráficos? estilo voxel? Y recomendada por lightbug? Dónde firmo para pagarlo hasta a plazos jaja
  27. 1 like
    eso es. alarga el indicador, para que pase del punto de contacto. a ver, yo te puedo bakear alguna texturas, no soy para nada experto, pero algo si me defiendo.
  28. 1 like
    Tú estás trazando un rayo desde donde disparas la bala hacia adelante, que es la forma típica de disparar una bala y calcular a qué collider le da instantáneamente. No necesitas que la bala tenga un collider ni un rigidbody para esto (de hecho si tienes muchas balas, mejor que no lo tengan). Esos 100f recuerda que son la distancia máxima e igual tu mapa es mayor. Y recuerda que si el origen del rayo está dentro de un collider esa colisión no la detectará. Pero lo que preguntaste es sobre el objeto "que está colisionando" con un collider, y eso normalmente no involucra raycasting. En vez de preguntar lo que quieres hacer, es mejor comentar qué problema tienes o qué quieres conseguir. Lo que has hecho está perfecto para balas instantáneas. Si a la bala le afecta la gravedad, el viento o el tiempo, entonces tienes dos opciones: simular la bala en el tiempo como un rigidbody y usar un modo de detección de colisiones Continous o ContinuousDynamic (de lo contrario a velocidades altas perderás colisiones) simular la bala a mano, trazando un rayo en cada FixedUpdate, desde la posición anterior hasta la nueva, alternativamente usando spherecasting en lugar de raycasting si es que es una bala enorme... en ambos casos perderías colisiones con otros objetos que también se muevan muy rápido (por ejemplo, otras balas) En todos los casos recuerda usar una capa para las balas (si es que al final tienen colliders) y otra para los objetos con los que sí quieres colisionar. Cuantos menos objetos haya en esa capa mejor, y utiliza la LayerMask para calcular el raycast sólo con los objetos que te interesen y ninguno más (el raycast y las físicas son computacionalmente costosas).
  29. 1 like
    Ya lo he probado, he llegado hasta una pantalla que ya no fui capaz de seguir. Pros: Es realmente entretenido y original La progresión de dificultad está bien pensada en mi opinión Es rápido, permite hacer muchos intentos seguidos. Cuando se pierde, inmediatamente nos redibuja el nivel (efectiva animación, por cierto) No pros: Se me hace raro disparar hacia donde salen los cursores, esperaba que la bola fuese en sentido contrario (quizá es mi sesgo de juegos de minigolf). La publicidad se me hace insufrible, a veces parece que en 3 ó 5 disparos ya me clava otro anuncio y no relaja. Después de un rato, se hace un poco monótono (coincide con cuando se me hizo difícil, o quizá estaba cansado, no sé). Para que vuelva a jugar, necesitaría algún aliciente (aunque yo juego muy poco a todo). El uso de las barras negras, se intuye que son indestructibles, pero podía haber más y dejar más claro que son indestructibles (un outline de otro color?) El espacio vertical y la pantalla cuadrada permite afinar o disparar más cómodamente en los tiros verticales que en los horizontales. Lo dejé en la pantalla con varias barras apiladas arriba y abajo. Y por cierto la publicidad funciona. Vaya si funciona.
  30. 1 like
    Si estás constantemente acortando la diferencia de ángulos en algún momento se va a dar que esta diferencia será menor, incluso si pegás el giro de 180. Primero y principal, con respecto al tema del giro, no hace la diferencia, podés usar cualquiera de los dos. En el video no se usa CharacterController, ese fue el nombre del asset que escogí. El personaje del video es un rigidbody dinámico con rotación bloqueada (físicamente hablando), el cual fue programado casi meticulosamente para que se mueva así (sobretodo para los benditos steps). Podría ser tranquilamente un rigidbody kinemático también (totalmente controlado por un script). ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- El personaje kinemático usa un rigidbody en modo kinemático. El CharacterController es una implementación de Unity de un kinemático, copiando la implementación de Nvidia. En internet existe un guerra, a ver quién puede hacer esto o aquello, el Kinemático es mejor, el dinámico es mejor, y así hasta el fin de los tiempos. Este CC es muy preciso, vos le decís "movete de la pos A a la B" y el personaje (basado en sus reglas internas de slope, steps y collide&slide) se moverá colisionando con el mundo de manera continua (no discreta) hasta llegar a B o C (nueva pos resultante). En la sig imagen, discreto arriba, continuo abajo: Super improtante: la detección de colisiones se debe implementar de cero usando Raycast, spherecast,capsulecast, etc ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Por otro lado el dinámico usa un rigidobdy dinámico con rotación bloqueada (usualmente). Hay formas y formas de usar un RB dinámico. Muchas veces te van a decir que ni se te ocurra cambiar la velocidad directamente de un rigidbody porque estás pisando su comportamiento base, y es cierto. En este caso es conveniente usar Fuerzas, estas se traducen a velocidades y estas últimas finalmente a posición, así las físicas se encargan de determinar todo por vos. Además tenés detección de colisión "gratis", tu único trabajo es mover el rigidbody. El personaje del video no hace esto último, hace rb.vel = Valor , y yo de fondo modifico este valor según mi propia gravedad, velocidad de movimiento, impacto externo (de otros rigidbodies), etc. Por esta razón se ve "snappy" y super preciso. En resumen es un dinámico que se mueve como un kinemático ;) (o también un kinemático con detección de colisiones y físicas gratis). Saludos
  31. 1 like
    Muy bien, lo estare probando. Hay muchos pasos, restricciónes y esperas para que admob funcione correctamente, si todo está correcto en unos dias tendras impresiones (15 aprox.) de lo contrario te llegara una notificación a Google Console para solucionar el problema.
  32. 1 like
    Wooow, muy bueno, el ejercicio está en decir como ha hecho eso. Tengo una pequeña idea pero no estoy seguro. Cuando saca la foto lo que hace es ubicar un prisma donde se proyecta la foto (2D). Con esto crea un nuevo modelo 3D basado en la intersección de este prisma con la geometría del nivel (si intercepta un rigidbody supongo que lo guardará entero o con un meshCollider resultado de la intersección(?)). Finalmente lo ubica en el mundo. Obviamente más allá de la técnología de fondo la idea está genial.
  33. 1 like
    1º Tomas 2 muestras del ángulo en el eje Y del objeto. BackFrame CurrentFrame 2º Obtener la diferencia absoluta de las muestras Math.Abs(CurrentFrame - BackFrame). 3º Creas tu propia fórmula para obtener un valor del 0 al 1 según el valor de la diferencia. Ejemplo, suponiendo que la diferencia máxima sea 20. 1 - Clamp(diff, 0, 20) / 20 4º Multiplicas la velocidad de movimiento con el resultado del paso 3.
  34. 1 like
    Veo 3 formas: Por código: simplemente midiendo el angulo de diferencia entre el ángulo "forward" del modelo (o ficticio puede ser también) y el vector de dirección de movimiento. El truco está en que la rotación se ejecute siempre, pero no el movimiento. Este último solamente se ejecutará cuando el ángulo entre forward y dir sea menor a X. Por estados del animator + root motion: basicamente los giros de personaje y los desplazamientos son animaciones que pueden o no estar "centradas" (me refiero a que el modelo puede moverse hacia cualquier lado --> https://kybernetikgames.github.io/animancer/docs/examples/locomotion/root-motion/root-motion.gif)). Dependiendo del ángulo del punto 1 se dará un estado u otro (generalmente se suele enviar este ángulo como una variable a un Blend tree, de acá se determina el clip resultante). Entonces si el angulo es menor a un valor se dará el clip de movimiento, si no se dará el giro. No haciendo nada ;) : Muchas veces queda bien y pro no hacer nada, en mi caso juego con la velocidad del Slerp para ver como queda (esto junto a la velocidad de caminar/correr). Ej: En caso de estar corriendo o incluso caminando vas a tener que reducir la diferencia max o directamente incrementar la velocidad de giro. Este giro que querés hacer se suele usar mucho más de "Idle" y no tanto en "Walk", "Run" etc. O por lo menos usarlo más en idle e ir reduciendo su influencia en estados más "dinámicos" (se me ocurre Assassins creed como ej).
  35. 1 like
    Buenos días y gracias por responder. Este vídeo ya lo había visto y "soluciona" entre comillas el problema de un modo muy parecido a como he dicho antes de crear un pivote para el movimiento, solo que el lo soluciona sin crear pivote y con cálculos matemáticos, pero así realmente no soluciona el problema porque si nos fijamos en el vídeo se puede ver como cuando va hacia delante y gira hacia la cámara el personaje rota mirando a la cámara de forma instantánea y no lentamente como debería de hacerlo y si regulase esa velocidad de giro, le pasaría que mientras va girando ya está moviéndose pero de lado hasta recolocarse en su angulo y se vería muy antinatural. Supongo que no queda otra y que esa es la solución (con un pivote o sin el) solo que no queda del todo bien porque habría que acompañar la rotación con una animación donde pusiera el pie de otra forma para que se viese mas natural o algo así... un jaleo. Por cierto, yo he programado todos estos movimientos del personaje en relación a la cámara de una forma mucho mas intuitiva y que se entiende mejor, porque para entender lo que ha hecho en el vídeo tienes que saber mucho de matemáticas y yo soy mas de lógica y no me enteraría en la vida. El problema es simplemente como hacer que primero rote y después comience a correr en la dirección deseada, sin correr de lado ni hacer cosas raras. Un saludo.
  36. 1 like
    puedes añadirle una pequeña aceleracion y asi le costara un poco empezar a andar y tendra tiempo para primero girar. si pones el trozo del script que se dedica al movimiento/giro quizas podamos ayudarte mas.
  37. 1 like
    Pues más crack todavia!!
  38. 1 like
    Este importador en realidad lo quería para Anastutia . Empecé esto escribiendo una herramienta para poder hacer mapas de minigolf proceduralmente, pero en Anastutia necesito enviar los mapas al jugador en tiempo de ejecución (ya que en Anastutia los minijuegos los genera y envía el servidor para que sean nuevos e iguales para ambos jugadores). Pero como conozco el mundillo GIS pues le di un intento a usar OSM y por ahora sigo con ello. Lo cierto es que por tiempo o interés siempre tengo todos los proyectos a medias. El generador que estoy escribiendo funciona: dándole las coordenadas de la zona del planeta que quieres generar dándole los datos de OpenStreetMaps de esa zona y una cantidad razonable de alrededores (podrían recogerse automáticamente pero para poner esto accesible, deberías usar tu propio servidor mirror de OpenStreetMaps) dándole un modelo de elevación de esa zona, idealmente con una resolución razonablemente buena (~35m/pixel) dándole un mapa global de densidad de población (~500m/pixel) - usado para algunas heurísticas (densidad de casas y cosas así) wishlist: en el futuro, dándole también las ortofotos de satélite (para detectar texturas, tejados, alturas de edificios, tipos de monumentos, árboles...) Yo trabajo con esto y suelo tener todos estos datos para países enteros en mi disco duro. En cualquier caso, todos esos datos son públicos para la mayor parte del planeta. Pero como ves, esto siempre estaría ligado a un servicio para que un usuario normal pueda recoger esos datos (hablamos de TB de datos para todo el planeta). Usar servicios públicos para un juego normalmente contraviene sus términos de uso, siempre podríamos usar nuestros propios servidores pero ves el problema... Mi generador es bastante simplón y tarda varios segundos/minutos en correr para generar 1 km2. Lo que hago es ejecutarlo offline e importar luego el modelo en Unity. Después lo postproceso para añadir colliders y cambiar materiales (y en el futuro, lo que haga falta). Podría hacerse esto online (el usuario tendría que esperar un poco pero sólo la primera vez), pero dependeríamos de un servidor propio haciendo ese proceso y de tener acceso a todos los datos mencionados antes para todo el planeta (algunas fuentes son muy diversas y algunas no están disponibles). Por ello, ahora mismo me planteo más bien generar mi ciudad, importarla a mano, cocinar la luz, hacer un juego sencillo, y luego ya veremos. Hay un pequeño problema adicional: mi generador proyecta el terreno sobre un plano. Como (casi) todos sabemos hoy la tierra ha resultado ser más bien una esfera y esto hace que no pueda generar muchos kilómetros a de mis coordenadas de origen sin horribles distorsiones. Mi generador no puede generar todo el globo a la vez (como sí hacen Google Maps, CesiumJS o VTS). ¿Por qué no en C#? A mí me interesaba escribirlo en Python, poder ejecutarlo en Linux, y poder generar modelos fuera de Unity. De esta forma, puedo correrlo en un servidor o como API sin necesitar Windows o Unity. Puedo usarlo para renderizar con Blender o hacer análisis de inundaciones, yo qué sé. No me gusta usar Unity para nada más que la simulación. La herramienta que mencionas, VTS Geospatial, es un conjunto de herramientas para gestionar, mezclar, servir y consumir datos GIS (mapas raster y modelos 3D). En particular, que yo sepa no proporcionan un algoritmo mágico para generar el terreno en base a fotos. Estoy seguro de que tienen acceso a una: esto es lo que hacen Google Maps o el equipo de Microsoft Flight Simulator, aunque también tienen nubes de puntos de LIDAR. En el ejemplo que enseñas esa herramienta está obteniendo la geometría 3D de los servidores de Melown Technologies, que es la compañía detrás de VTS Geospatial, y no sé si tienen disponible todo el planeta, pero desde luego no sería gratis. No he podido probarla, lo siento, pero si comentas el error que ves en otro hilo igual podemos sugerir algo. Pero en cualquier caso: hay una diferencia fundamental entre el estilo de esas herramientas y la síntesis desde OpenStreetMap. La generación desde imágenes y nubes de puntos no accede bien a zonas ocultas y a menudo genera artefactos muy extraños tanto en el modelo como en las texturas. Los túneles a menudo aparecen tapados o mal conectados. La inteligencia artificial falla en objetos inusuales o desconocidos (aunque esto ya es cada vez menos cierto, y Google está generando unos modelos impecables de cosas como grúas). Es difícil eliminar sombras, vehículos y otros objetos de las texturas y modelos. No capturan objetos pequeños (farolas, semáforos, papeleras). Pero lo más importante, estos mecanismos no separan los diferentes objetos, no saben qué es una grúa, qué es un monumento y qué es parte del edificio del al lado... no tienen información semántica. Aunque no faltará mucho para que hagan todo esto. OSM es un mapa simbólico, y tenemos datos exactos, los nombres de las calles y monumentos, velocidad y direcciones del tráfico, y metadatos que "representan" una ciudad. Así, al generarlo de forma procedural, sabemos que una calle es una calle y podemos poner semáforos, papeleras y decoración en sitios adecuados, y permitir que el usuario/jugador interactúe con ellos. No es remotamente fiel a la realidad, pero nos permite generar un mundo más inmersivo. De esta forma, se pueden generar algo que se parezca al mundo real, pero también podemos generar mundos de fantasía simplemente mapeándolos. Podríamos incluso construir así interiores y edificios procedurales usando herramientas de mapeado. Podemos cambiar el estilo global o de las zonas parametrizando el generador o customizándolo.
  39. 1 like
    hola, si, yo te estaba diciendo de otro tipo de material.... donde pone shader, arriba del todo, tu tienes puesto "specular"... yo creia que estabas usando el "standard", y hay uno que se llama "standard (specular setup)"... te decia que usases ese... entonces te sale un recuadro donde pone specular y ahi puedes asignar una imagen... ...lo siento, estoy intentando subirte unas imagenes pero me da error todo el rato... sera porque lo intento con el movil? de todas formas no se que shader specular estas usando... que version de unity tienes? porque mi shader specular normal se llama "legacy shaders/specular"...me parece muy raro que solo te ponga "specular" donde el shader... de todas formas si no tienes el shader "standard (specular setup)" (que me parece muy raro) puedo hacerte un shader "a medida" que haga justo eso que quieres.... es muy facil
  40. 1 like
    el material standard specular tiene la posibilidad de asignarle un textura de specular, en la que los tonos mas claros serian zonas con mas brillo. haz una copia de tu textura de la ventana, y ponle donde el cristal en blanco y las zonas que quieres sin brillos ponle esas zonas en color negro.
  41. 1 like
    No, porque los mensajes de collision se disparan cuando los objetos colisionan, en este caso cuando "entra" en una colisión. Creo que se dan cuando la distancia entre los puntos más cercanos es menor a la suma de los contact offset de los dos colliders (ProjectSettings/Physics(o Physics2D)). Con raycast, spherecast, y demás vos estás "prediciendo" el futuro choque (dependiendo de las características del "cast" obviamente). La desventaja es que necesitas "castear" (ya que estamos vamos a cagarnos en la RAE xD) todo el tiempo, y el cast necesita ser fiel a la forma del collider (si usas una caja será un boxcast, si es una capsula un capsuleCast, etc). En 2D (no se en 3D) tenés Rigidbody.Sweep, es más caro pero hace el cast con toda laforma del collider2D. Lo que sí podés hacer con los "cast" es filtrar por capas usando LayerMasks, y posteriormente usando tags.
  42. 1 like
    xD no entendí absolutamente nada de lo que dijo pero me mantuvo pegado a la pantalla todo el tiempo. Si un gameplay de estos llega a pewdiepie o markiplier andá agrandando tu casa, para que entren los dólares jaja.
  43. 1 like
    Es un pequeño juego 2D creado para la JAM de UnitySpain. Tienes que guiar al personaje por el bosque hasta que llegue a casa. El juego es tranquilo, se trata de ir encontrando los diferentes caminos y esquivar los peligros que se encuentra como los lobos o las lanzas. Creo que le dedique mas o menos unas 16 horas, y estoy contento con el resultado, tanto que me quedo con el proyecto para irlo evolucionando poco a poco, ya ire compartiendo los cambios y los "improvements". Cualquier idea, o crítica, que querais aportar sera muy bienvenida. Por ahora esta disponible en itch.io: https://uadla.itch.io/way-home
  44. 1 like
    Me gustaría saber qué credenciales profesionales y académicas tiene cada uno para decirle al resto del mundo cómo tiene o dejar de hacer las cosas. Saludos
  45. 1 like
    Unity está dejando de ser, por los keynotes que voy viendo, en un motor de videojuegos para ser un motor para todo tipo de aplicaciones. Plantean en el último keynote que los módulos de AR y MARS sean accesibles de manera independiente desde apps nativas. Justo lo contrario que planteas. Además han creado módulos específicos para arquitectura, para automoción, para industria, para ingeniería, etc. Y no es algo que escondan, está en la página principal de Unity. Si hablamos de rendimiento, entonces por esa misma regla de tres, dado que un videojuego es mucho más intensivo en recursos que comparado con una app con soporte de Google Maps, los videojuegos deberían crearse todos en código nativo y no en Unity. Al final es un equilibrio entre rendimiento y capacidades, y en el caso de Unity el apartado multiplataforma así como la cantidad de assets en la store, lo reequilibra a su favor. Y la filosofía de "caja negra" va a dejar de existir a medida que se implante DOTS, ya que podrás debugar directamente sobre el código nativo de Unity. Hasta modificarlo si lo deseas. Creo que Unity está evolucionando y abriendo otros caminos en el desarrollo multiplataforma. El desarrollo de videojuegos exclusivamente y con alto rendimiento habrá que dejarlo para engines como Unreal, pero desde luego no Unity. Y eso no es malo, todo lo contrario. Es un mundo fabuloso el que se abre. Saludos
  46. 1 like
    Buenas, como ya se ha hablado por las redes de UnitySpain se re-abre este hilo para que podáis ir subiendo los WIPs, y tener todo de una forma un poco más organizada. ;D Para los despistados. Desde hace unos días ha habido bastantes usuarios interesados en introducirse en el mundo del modelado 3D, para ello se ha planteado un ejercicio; modelar un ajedrez.. Actualmente hemos entrado en la dinámica de que enseñan pieza a pieza y dentro de lo que cabe, se trata de darle las correcciones pertinentes. Y como digo ahí arriba , a favor de tener una forma más organizada donde llevar el tema, sin estar colapsando las redes, a partir de ahora se utilizará este post. -- Si cualquier usuario quisiese sumarse a la causa y no sepa ni por donde empezar, que no se preocupe y que avise por aquí, y tratamos de darle un poco de orientación básica para empezar con el ejercicio ;D Algunas de las correcciones u observaciones del post anterior: Un aspecto importante que os está costando distinguir es diferenciar tener dos objetos "combinados" o "unidos". Vamos a intentar diferenciarlo y ver dos ejemplos: Combinar: Permite gestionar dos mallas como un objeto unitario. A pesar de ello, los objetos conservan cierta independencia, permitiendo por ejemplo aislar uno de el otro mediante una selección de todas las caras de uno de los objetos combinados. Unir: Es la "fusión" de dos objetos. No solo se gestiona como un objeto unitario, si no que lo es. Los dos objetos sestán "soldados". En la imagen podéis ver la diferencia. Estando el objeto de la izquieda unido, y el derecho combinado. Combinar geometría, no es una práctica errónea, pero justamente este ejercicio está enfocado a aprender a solucionar geometría sencilla, evitando que fragmentéis en partes piezas que pueden ser solventadas como una pieza única :D Tanto así, existen una serie de "normas" que debe cumplir una malla para estar hecha correctamente. Esto no significa que no se puedan hacer excepciones, pero no viene al caso. Así que sobre todo para este ejercicio (en casi en toda malla, vamos) buscamos las siguientes características. Malla homogénea. Solo polígonos de cuatro vértices (ni más ni menos). No tener vértices sin soldar . Intentar evitar estrellas (vértices donde se unen más de 4 aristas) _____________________ Por otro lado parece que estáis teniendo ciertas dudas a la hora de la presentación, es importante que tengáis dos cosas presentes. Si utilizáis fondo aseguráos de que es un color diferente a vuestras piezas, si no es practicamente imposible nada. A la hora de presentarlo es imporante que adjuntéis ina imagen "shaded " y otra con el "wireframe" Si me dejo algo en el tintero ya haré un edit, dicho esto ... A modelar !!
  47. 1 like
    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
  48. 1 like
    Mi primer vídeo juego en Unity 3D Personal. También hecho con MakeHuman y blender. Mi blog
  49. 1 like
    El mismo terrain de Unity quizás? Usa el de 2018.3, está mucho mejor que el viejo terrain, tenés stamps, capas separadas y reutilizables, todo en GPU supeustamente, más brochas, una calidad visual bastante mejor que el anterior. No se si acá estás confundiendo algunas cosas, eso que te da Unity es un límite para cada textura importada (cualquier de las dimensiones, alto o ancho), tus texturas son tus texturas, importá las de 4k (por ej) y ponele un limite de 256, o directamente redimensionalas manualmente en tu editor de preferencia, debería resultar en lo mismo (visualmente, no se en tamaño final). Lo que creo la mayoría te está diciendo es que con 3 o 4 texturas pequeñas y bien hechas podés hacerte tremendo terrain de los kilomentros que quieras, todo va en tener en cuenta y balancear algunas cuestiones, por ej: si elegís poner o no normal map u otros maps en cada una de las texturas, si realmente hace una diferencia visual. Te diría que se lo asignes a una capa que lo merezca como tierra o rocas si es hierba, pasto o arena se podría llegar a omitir. si querés que el mapeo UV sea de tal forma o de otra, supongo usando algun shader "inteligente", ruido, planar o triplanar(este ultimo queda excelente en terrains si la variación la querés crear incrementando las dimensiones, osea manteniendo el detalle vs perder detalle, incrementado la variación pero manteniendo las dimensiones (esta ultima puede que no resulte, el cerebro humano es extremadamente bueno detectando patrones), revisá el ejemplo de más abajo. La plataforma de destino, por supuesto. Lo de las dimensiones tan pequeñas no se, depende del detalle que quieras lograr para la distancia a la que ves al terrain la mayor cantidad de tiempo de gameplay. LA técnica de dibujado y la variación también importan, por ejemplo, usando 2 capas distintas con la misma información de textura ( usando una para albedo y otra para normal) de 512x512: - Usando una sola capa: >Capa 1 >Capa 2 usando 2 capas (más agradable de ver, no es perfecto pero lo hice en 4 segundos): Exagerando para ponerla en evidencia la diferencia: AMbas capas tienen distintas propiedades de material, haciendolas aun más aleatorias al ojo humano . Además todo esto lo podés hacer "on the fly" sin idas y vueltas. Quizás "La razón" por la que no usar programas de modelado para un Terrain, la iteración que perdés yendo y viniendo (y ni hablemos de texturizar) desde un programa externo al motor es inmensa, acá das un par de clicks y ya está, entiendo si estás tratando de hacer agujeros en el terrain o cosas similares, yo los hacía en blender pero justamente sufría de esto que menciono, texturas enormes y la falta de respuesta si pretendo modificar algo al toque. Puedo entender la frustración especialmente con Unity, pero puedo dar fe que con el nuevo terrain han mejorado algunas cosas, sobretodo cuando cambias las dimensiones el terrain se estira (antes se borraba toda la info), lo mismo mejoró con el tema del detalle, antes tocabas algo y *Chuf* ya no está todo el grass que te pasaste horas poniendo. También podés agregar terrains vecinos, programar tus brochas, estampar terrain y ver el resultado antes de dar click, capas y demás, esta mucho mejor. Saludos
  50. 1 like
    Este asset ya lo había subido hace un tiempo en "Recursos", pero bueno, aca dejo la versión "asset store" así queda para las futuras generaciones DESCRIPCIÓN Grab It te permite manipular "rigidbodies" agarrandolos, puedes moverlos, rotarlos, acercarlos/alejarlos o arrojarlos. Esta mecánica de juego se hizo popular en el genero de horror, especialmente impulsada por Frictional Games en juegos como los de la serie Penumbra y Amnesia: The Dark Descent, el objetivo principal de este asset es emular este comportamiento. La mecánica es simple de ejecutar, simplemente mira directamente al objeto (idealmente con una cámara, pero funciona con cualquier objeto que tenga una dirección de forward) y presiona/mantiene el botón izquierdo de mouse, si el objetivo es un Rigidbody será afectado (previamente filtrado por el layermask). Suelta el botón del mouse y podrás soltarlo. Actualmente hay dos tipos de rigidbodies soportados, RB "normales"(por ejemplo una piedra, un ladrillo) y hingeJoints (por ej puertas). ESPECIFICACIONES - Agarra cualquier Rigidbody. - Mueve al Rigidbody mientras lo sostines. - Rota al Rigidbody mientras lo sostines. - Acerca/Aleja al Rigidbody mientras lo sostines.. - Controla hingeJoints de manera apropiada. VIDEOS DEMO WebGL Descargalo gratis del asset store ---> GrabIt
×
×
  • Create New...