Jump to content

Archived

This topic is now archived and is closed to further replies.

Jhonatan00_00

ANSWERED Físicas con CharacterController

Recommended Posts

Muy chulo el diseño y la iluminación. No podríamos ver un vídeo para ver cómo se mueve y las lights?

Share this post


Link to post
Share on other sites

Gracias iRobb, la forma de moverse es muy suave. Intento que se sienta como si jugases a una videoconsola pero en PC, por lo que el movimiento del personaje es suave jugando con las teclas, nada de giros bruscos, se ve y se siente bien. La iluminación es estática... solo que juego con luces, etc para hacer efectos de fuego, día, noche, etc... Hay que sacar el máximo partido de la potencia del PC y si hago las sombras en tiempo real (que a parte Unity 4 free no tiene) consumo mas recursos que puedo usar para otra cosa.

Por eso no quería actualizar a una versión mas nueva de Unity, porque la iluminación aunque sea también bakeada no se ve igual en las últimas versiones y el juego pierde esa magia y esa ambientación. Tengo que actualizar y hacer pruebas porque también necesito sombras en tiempo real, pero todo esto mas adelante.

Ya subiré una demo o algo mas cuando pueda, pero antes tengo que hacer otras cosas.

Saludos.

Share this post


Link to post
Share on other sites
1 minute ago, Jhonatan00_00 said:

aunque me tengan por un tonto que no ha programado nada en su vida,

Nadie te toma por tonto (por lo menos con maldad), acá no todo el mundo sabe programar, esta no es la razón de las "tomadas por tonto". Da la sensación de que ninguna respuesta es aceptada, como que siempre falta algo más.

Tampoco tomes tu pasado como una certificación para decir que sabés tal o tal tema. Unity no es Blitz (subrayado y en negrita porque veo que lo mencionas cada 3 post), yo también he usado Blitz, Unreal, Shockwave, Flash, 3D GameStudio, 3DS max (con una herramienta para hacer juegos, ni me acuerdo), Blender, (además de vivir en 3DGameEngines.net) . Antes de Unity ya había programado en Assembler, C, C++, Javascript,  etc etc, pero al momento de poner pie en Unity + C# era simplemente un ignorante más, me sirvió lo anterior? sí claro, pero de Unity no sabía nada.

 

2 hours ago, Jhonatan00_00 said:

Por cierto, Unity SI es gratis, no como me dijiste en otro tema que era de pago y te reiste de mi como siempre... Unity solo se paga cuando superas los 100.000 dólares al año

Bueno, ahí esta el error. Por favor tené en cuenta que estás lidiando con programadores (en su mayoría), si existe una mínima condición que impida la condición de gratuito del motor (en su totalidad), entonces la afirmación será falsa. Y no estoy hablando del famoso "Free software", que ahí ya nos vamos de mambo.

Me parece que acá el problema es que no se está hablando del qué es gratuito con respecto a Unity (francoe se refiere a Unity y vos al uso de Unity). Con decir al aire "Unity es gratuito", cualquiera lo podría entender a que se puede obtener Unity sin pagar y listo. Por obtener me refiero descargar sin pagar, a usarlo como se me dé la gana (como por ejemplo Blender, o Gimp). Entonces, si vos te descargas Unity, podés hacer lo que quieras con él? no, tenés planes y licencias que debés respectar.

Esto no imposibilita que puedas descargar y usar Unity gratis (un plan de su modelo de negocios) para ganar pasta con tu juego (con algunas limitaciones: ingresos, splash screen, el skin de editor, y algunas que otra cosas más). Muchas veces esto último es lo que a la mayoría de nosotros realmente nos interesa, y está perfecto decir que Unity se puede descargar y usar de forma gratuita, siempre y cuando se respeten un conjunto de reglas.

3q6sxj.jpg

 

41 minutes ago, Jhonatan00_00 said:

pero cuando instalé la última versión de Unity tanto la iluminación como otros muchos aspectos de mi proyecto ya no eran compatibles o iguales y cambiaban por completo

No, claro, pensá que Unity cambia muchísimo... pero taaaanto, que un proyecto de 2019.1 quizás no ande directamente con todo correcto en 2020.1. Estoy hablando de 2019 a 2020 (por este tipo de cosas se recomiendan las LTS). Como vas a pretender que ande de 4 a 2017/18/19/20 ?? Sobretodo en iluminación, los assets van y vienen (sobretodo meshes, sprites, y demás). Ni hablemos del código, por favor.

Share this post


Link to post
Share on other sites

@lightbug Gracias por responder

@Jhonatan00_00 Te recomiendo que leas "Términos de uso" y dentro de esto verás el por qué Unity no es "gratis". 

Si querés nos sentamos a discutir SEO y te explico cómo funciona. 

Y por último una gran recomendación, no consumas esas porquería de geinxu, alva majo, etc... Esa gente está al mismo o más bajo nivel que vos, la diferencia es que se crean una leyenda de si mismo. Creedme, hay video conferencia muy buenas de gente profesional, que trabajo para Rockstar, Ubisoft, THQ, Vivaldi y muchas otras grandes empresas, no es necesario que pegue el Link, están en Youtube! 

---------

Si, soy prepotente, y esto se debe a que trate con mucha gente igual que vos, con más preguntas que conocimiento, con más ganas de soluciones instantánea que de aprendizaje. Con la experiencia te irás volviendo más arrogante y menos tolerante.   

Sin embargo, acá, en el foro, muchas veces respiramos profundo e intentamos responder de la manera más orgánica posible, para que quien pregunta entienda.

-------

El proyecto se ve bien, pero 1 imagen no refleja absolutamente nada, compartir un GIF o Vídeo sería de agradecer, aparte, es una forma generosa de devolver lo que el foro te está dando de forma gratuita. 

7 hours ago, iRobb said:

Vaya con el vídeo. Hace 20 años se reían de nosotros y ahora nos vengamos. Es la venganza de los nerds! 

Por cierto, minuto 1:05 cuando dice "respeta a los demás porqué..."  y  se queda en blanco. Jajajaja

Lo mejor de todo es que el ejemplo del 1:05 es muy malo, no se aplica a lo que intento exponer. Es decir, mezclo profesiones... 

Si vas a programar cómo junior dentro de una empresa serás tratado como tal, el día que sea semi-senior o senior entonces podrás elegir si tolerar a los Juniors o dejarlos en libertad jajajajajaja

Share this post


Link to post
Share on other sites

Buenas tardes, estoy tratando de poner en práctica la solución que me indicó LightBug y me funciona un poco raro, solo empuja a los objetos a veces y cuando caigo sobre ellos...

En este video tutorial lo explican todo paso a paso: 

Lo he seguido al pie de la letra y no consigo comprender:

1º) Como al principio del tutorial consigue hacer mover el cubo con RigidBody sin tener un RigidBody el personaje asignado si no un CharacterController. A mi no me deja empujar nada si tengo solo un CharacterController.

2º) Como sin agregarle tampoco un Collider consigue usar el Script para mover objetos y que le funcione. A mi me funciona pero mal y solo si asigno un collider al personaje, si no nada.

¿Que puedo estar haciendo mal?. :40_rage: 

Share this post


Link to post
Share on other sites

Hola @Jhonatan00_00, al parecer en el video el movimiento se debe a que el jugador se está moviendo modificando la posición directamente (CharacterController), puede existir un Physics-Step entre el movimiento y el "re acomodamiento" que genere una colisión dentro del collider de la caja que contiene el Rigidbody. En resumen, por x cantidad de tiempo el jugador está traspasando al cubo. Esto una hipótesis. 

Por la foto y otras preguntas ahora entiendo que el movimiento del jugador se basará en 3D, esto es muy importante, en principio te diría que elimines la posibilidad de hacerlo con Raycast, en 3D es un poco más complejo de asimilar que en 2D y sin los conocimientos matemáticos necesarios es bastante dificil lograr un buen resultado.

¿Como simular la física de contacto?
Es simple, character controller utiliza un Capsule Collider para detectar sus colisiones, podrias crear un Componente que detecte y lanze un evento de colisión con todos sus contactos.

public class CollisionManager : MonoBehaviour
{
  	public delegate void CollisionDelegate(Vector3 point, Vector3 normal, Transform go);
  	public event CollisionDelegate CollisionEvent;
  
    private void OnCollisionStay(Collision collisionInfo)
    {
        foreach (ContactPoint contact in collisionInfo.contacts)
          CollisionEvent?.Invoke(contact.point, contact.normal, contact.transform);
    }
}

Ahora capturas el evento y compruebas si el objeto colisionada contiene un rigidbody, luego aplicas la fuerza en el punto de contacto con su normal y la velocidad del jugador (la velocidad del frame anterior).

public class CharacterControllerPhysics : MonoBehaviour
{
  [SerializeField]
  private CollisionManager m_collision;
  
  private void Awake()
  {
    m_collision.EventCollision += OnCollision;
  }
  
  private void OnCollision(Vector3 point, Vector3 normal, Transform go)
  {
    if (TryGetRigidbody(out Rigidbody rb))
      rb.AddForceAtPosition(normal * PLAYER_CURRENT_VELOCITY, point);
  }
  
  private bool TryGetRigidbody(Transform t, out Rigidbody rb)
  {
    rb = t.GetComponent<RigidBody>();
    return rb != null;
  }
}

PLAYER_CURRENT_VELOCITY debería ser el valor de la velocidad del frame anterior. 

Esta es la forma más sencilla de hacerlo, existen alternativas con mejores resultados pero aumentan proporcionalmente su complejidad. 

Share this post


Link to post
Share on other sites
12 hours ago, Jhonatan00_00 said:

Lo he seguido al pie de la letra y no consigo comprender:

1º) Como al principio del tutorial consigue hacer mover el cubo con RigidBody sin tener un RigidBody el personaje asignado si no un CharacterController. A mi no me deja empujar nada si tengo solo un CharacterController.

Eso va a depender de la colisión en sí. El CC lo que hace es proyectar su forma y decir "movete hasta ahí", pero no la hace de manera perfecta, en algunos casos simplemente queda un poquito penetrado en el collider. Si esto pasa, es posible que la "caja" lo detecte y sea empujada (por la misma simulación de físicas).

--> Es un comportamiento deseado? No, no lo es, es un efecto no deseado, la caja no debería ser empujada nunca. Así que, si no te pasa, mejor.

Por qué pasa esto? bueno, por situaciones de la misma escena, la forma del collider, la velocidad del personaje, la forma del personaje, por el ángulo de incidencia, etc etc.

 

Por ej, also similar pasa en mi character controller. Si considero los rigidbodies dinámicos (caja blanca del gif) y los habilito para la "detección de objetos estáticos" (un layermask del personaje), lo que pasa es lo mismo que en tu caso, el personaje se proyecta con capsuleCast y detecta a la caja (en el gif no se ve ningun movimiento, como debería ser). En el segundo caso, sin considerarlo como estático (es decir sin que el capsule cast lo detecte) simplemente interactura normalmente, usando las físicas (que sería un "equivalente" a usar el callback en tu caso, aunque no es exactamente igual).

CCP-Col.gif

Otra cosa que vas a tener que tener en cuenta es que las colisiones que hagas no van a ser "perfectas", con esto me refiero a que pasa lo siguiente:

  1. Se mueve el personaje hasta la caja (pegadito a ella).
  2. Se dispara el callback
  3. Se le da una fuerza a la caja

Como ves, nunca vas a estar pegado + empujando la caja, siempre va a haber un pequeño espacio, que dependiendo la velocidad y fuerza de aplicación será más o menos notable.

Lo ideal sería mover también al CC luego de haber empujado la caja, pero tendrías que esperar hasta después del step físico para saber donde va a terminar esta... sí, complicado. En estos casos podés usar algo que se llama PhysicsScene para meter a la caja sola en la escena, resimular el step físico, ver donde terminará la caja, y luego ahí posicionar el CC. Pero bueno, esto lo menciono medio a laire, si estás usando el CC de Unity no tiene sentido ponerse heavy con todo esto, con el callback debería darte resultados medianamente pasables.

Si tu caja fuera muy "predecible", quizás hacer a la caja kinemática pueda ser una opción viable, pero ya no estamos hablando de físicas reales ni nada, simplemente movimientos norte, sur, este y oeste, tipo un laberinto de pacman.

 

13 hours ago, Jhonatan00_00 said:

2º) Como sin agregarle tampoco un Collider consigue usar el Script para mover objetos y que le funcione. A mi me funciona pero mal y solo si asigno un collider al personaje, si no nada.

Sin agregarle un collider a qué? al personaje? el personaje tiene un CC que es (para las físicas) efectivamente considerado como un collider especial (esto lo podés testear con un OnTriggerEnter), pero sin reaccionar a nada, es kinemático basicamente.

La colisión se detecta entre un kinemático (personaje) vs dinámico (caja) y se llama al callback. Este callback brinda información (el parámetro), de ahí en más está en el programador en qué hacer con ella.

 

Saludos

Share this post


Link to post
Share on other sites

Buenas noches a todos, he estado un poco atareado y había dejado un poco el tema, pero ya estoy de vuelta. Finalmente no es tan complejo de solucionar como parecía, simplemente no me funcionaba tal y como lo explican en el ejemplo y lo que he tenido que hacer es lo siguiente:

void OnControllerColliderHit (ControllerColliderHit Objeto_Colisionador) {

        Empuje = new Vector3 (..., ..., ...);
        if (Objeto_Colisionador.collider.attachedRigidbody == null || Objeto_Colisionador.collider.attachedRigidbody.isKinematic) {
            return;
        }
        Objeto_Colisionador.transform.Translate (Empuje * 2);

    }

El problema es que si lo programo tal y como explican en la web de Unity, usando Rigidbody.velocity en lugar de transform.translate los objetos se mueven cuando les da la gana, a veces no detecta la colisión o no se y se mueven de una forma muy erratica, sin embargo con transform.translate si que los empuja solo con tocarlos como debe de ser.

Dependiendo de si pongo; Empuje = new Vector3... MoveDirection... Velocity... o simplemente Transform.Position los objetos se mueven pero hacia una dirección u otra y aún no he conseguido que la dirección sea según desde donde el personaje lo empuje, es lo que me falta por resolver.

Mañana le daré vueltas a ver si saco los valores a meter en la variable Empuje y lo arreglo, porque es solo eso y funciona... Por cierto, esto sirve para coger item y hacer cientos de cosas, pero no tenia ni idea. :7_sweat_smile:

Gracias.

Share this post


Link to post
Share on other sites
12 minutes ago, Jhonatan00_00 said:

El problema es que si lo programo tal y como explican en la web de Unity, usando Rigidbody.velocity en lugar de transform.translate los objetos se mueven cuando les da la gana, a veces no detecta la colisión o no se y se mueven de una forma muy erratica, sin embargo con transform.translate si que los empuja solo con tocarlos como debe de ser.

Eso está mal,  mover cuerpos rígidos dinámicos con transform (position o Translate) es una mala práctica. Probá volver a como estaba antes, seguramente algo estás haciendo mal, será la fuerza? será el peso? será el drag? la velocidad? estás usando interpolación?... las cosas no se mueven cuando se les da la gana, tiene que haber algo que se te está pasando, esto no solo depende del código, depende mucho de los valores de los componentes involucrados.

Empujá a la caja contra una pared, pero antes reemplaza ese "Empuje * 2" por un "Empuje * 20" y probablemente pase al otro lado, tipo efecto tunel. El "probablemente" no es un "seguramente", ya que al modificar este tipo de cosas donde no se debería hacer, terminás no teniendo certeza de nada.

 

Share this post


Link to post
Share on other sites

Se que está mal porque anulo las físicas, pero en este caso no las anularía, porque si tengo un objeto delante y lo único que quiero es moverlo y que por ejemplo caiga por una rampa, el empuje en si lo estaría haciendo con transform, pero conforme empezase a caer por la rampa ya si actuarían las físicas que es lo que me importa. No obstante lo he cambiado y lo he hecho con velocity.

Lo que no me entra en la cabeza es que cuando creamos la fuerza de empuje, lo que el ejemplo de Unity dice es que usemos moveDirection para saber la dirección hacia donde se mueve el personaje y aplicarla sobre el objeto, pero ese moveDirection no va asociado al personaje si no al objeto que empujamos y no se está moviendo, no lo entiendo. Así es como dice Unity que deberíamos de hacerlo:

void OnControllerColliderHit (ControllerColliderHit Objeto_Colisionador) {

vector3 Empuje = new vector3 (Objeto_Colisionador.moveDirection.x, 0, Objeto_Colisionador.moveDirection.z);

El objeto no tiene movimiento, por lo que el valor del moveDirection seria cero y solo en momentos en los que el personaje consiguiera empujar levemente al objeto es cuando actuaria alguna fuerza y funcionaria... pero mi personaje no suele empujar en absoluto ningún objeto y por eso no funciona. Como funciona es así:

void OnControllerColliderHit (ControllerColliderHit Objeto_Colisionador) {

vector3	Empuje = new Vector3 (GetComponent<CharacterController>().velocity.x, 0, GetComponent<CharacterController>().velocity.z);

Ahí si tenemos en cuenta la velocidad y el ángulo desde el que empuja el personaje y funciona, aunque no entiendo por que según desde el ángulo que le de al objeto a veces tiene mas fuerza y a veces menos... no reacciona siempre igual de bien e incluso me quedo empujando al objeto sin que se mueva a veces, como si estuviese pegado al suelo, depende del ángulo. 

Share this post


Link to post
Share on other sites

La fuerza es la dirección entre el jugador y el objeto.

vector3 dir = (jugador.posición - objeto.posicion).normalizado

Luego a ese vector de dirección lo multiplicas por la velocidad del jugador. 

dir *= jugador.velocidad.magnitud

Tenes que tener en cuenta la relación velocidad/fuerza/masa. Cuánta Fuerza se necesita para mover X Objecto con X Masa con X Drag, etc.

Quizás en el Ejemplo Unity contempla que el objeto tenga una velocidad al momento del impacto, las diferencias de fuerzas determinan si el objeto empuja al jugador o viceversa. 

 

Share this post


Link to post
Share on other sites

GRACIAS FRANCOE1!!, LA MADRE QUE ME PARIO!!, POR FIN LO HE CONSEGUIDO GRACIAS A SU ULTIMO MENSAJE!!.

void OnControllerColliderHit (ControllerColliderHit Objeto_Colisionador) {

		Empuje = Objeto_Colisionador.transform.position - transform.position;

		if (Objeto_Colisionador.collider.attachedRigidbody == null || Objeto_Colisionador.collider.attachedRigidbody.isKinematic) {
			return;
		}

		Objeto_Colisionador.rigidbody.velocity = Empuje * 4;

	}

Gracias de verdad, me tenia frustrado este tema. :4_joy:

Share this post


Link to post
Share on other sites

×
×
  • Create New...