Ir al contenido principal

Mi primera cámara en tercera persona con Unity3d

Hoy he conseguido implementar mi propia cámara en tercera persona, en Unity3d. El problema con la cámara estándar es que difiere un poco de la que implementa Unreal Engine, que se utiliza en Mass Effect y The Witcher 2/3, por mencionar algunos ejemplos clásicos. Recuerdo que la primera vez que jugué Mass Effect, los controles se me hicieron un poco molestos, sin embargo, luego me habitué al movimiento de cámara, y siemrpe quise tener algo igual.
A ver, en el modo tradicional, estilo MMORPG, la rotación de la vista se logra mediante las teclas de dirección (A/D). El modelo del personaje rota "arrastrando" la vista de la cámara. Ya implementé algo similar en Ogre3D, que permite hacerlo de forma muy fácil. El otro modo, la cámara puede mirar libremente en todas direcciones, desplazándose alrededor del personaje. Al pulsar una tecla de desplazamiento, el personaje rota para encarar la dirección en la que la cámara mira y entonces avanza. Increíblemente, nadie ha implementado algo así para Unity3d. o de haberlo hecho, no está muy accesible en internet.
El método que seguí quizás no sea el más óptimo, pero es que después de mucho preguntar nadie pudo darme una luz y mis conocimientos de matemáticas son muy pobres. La idea consiste en usar un GameObject pivote, que se mantiene sincronizado con la posición del GameObject del personaje. El pivote tiene un hijo que contiene la cámara, así que las rotaciones del pivote afectan esta cámara. Eso nos resuelve el free look:

if (Input.GetAxis ("Mouse X") != 0 || Input.GetAxis ("Mouse Y") != 0) {
            float rotationX = gameObject.transform.localEulerAngles.y + Input.GetAxis("Mouse X") * 2f;
            rotationY += Input.GetAxis("Mouse Y") * 5f;
            gameObject.transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
        }

Por su parte, el GameObject dle personaje se encarga de sincronizar el pivote cuando se mueve y orientarse en la dirección adecuada:

void Update () {
        pivot.transform.position = gameObject.transform.position;
        if (Input.GetKey (KeyCode.W)) {
            //determinar el angulo del personaje
            Vector3 rot = gameObject.transform.localEulerAngles;
           //del pivote, tomamos la rotacion en y, descartamos lo demas
            rot.y = pivot.transform.localEulerAngles.y;
            gameObject.transform.rotation = Quaternion.Slerp(gameObject.transform.rotation, Quaternion.Euler(rot), 5f* Time.deltaTime);
            gameObject.transform.Translate(0,0, 10*Time.deltaTime);
            pivot.transform.Translate(0,0, 10*Time.deltaTime);
        }
    }

Por supuesto, esto que ven aquí es un código muy chapucero hecho en una hora. Faltan montones de cosas por implementar y a finar, pero es un punto de partida (ayer tenía muchísimo menos que eso).

Comentarios