martes, julio 29, 2014

Cámara isométrica en Unity3d

Tengo el mal hábito de que lo primero que intento hacer en un motor de juegos es una vista isométrica. Si resulta fácil, entonces el motor se puede considerar como fácil de usar. Los juegos isométricos han caído en el olvido y no es de extrañar que los motores intenten facilitar otros modos de cámara más populares como primera y tercera persona.
Pensé que lo había conseguido en Unity en unos pocos minutos (gracias a Google), pero el efecto no era exactamente el deseado. Al final, logré darme cuenta de lo que estaba mal, pero eso lo veremos más adelante.
Para empezar, crea un GameObject vacío, que servirá como padre de la cámara. En aras de simplificar, digamos que estará ubicado en (0, 0, 0). Crea una cámara y hazla hija del susodicho GameObject. Las coordenadas de la cámara serán (15, 15, 0), también en aras de simplificar. Podría ser (0, 15, 15), pero en ese caso, tendrías que calcular las rotaciones a mano. Cambia la cámara a modo ortográfico, para conseguir el efecto más aproximado al isométrico antiguo.
Agrega este script C# a la cámara:

using UnityEngine;
using System.Collections;

// Camera Controller
// Revision 2
// Allows the camera to move left, right, up and down along a fixed axis.
// Attach to a camera GameObject (e.g MainCamera) for functionality.

public class CameraController : MonoBehaviour {

    //float Xmax, Ymax;
    int UP = 1;
    int DOWN = 2;
    int LEFT = 3;
    int RIGHT = 4;
    int dir = 0;
    int rot = 0;
    int RLEFT = 1;
    int RRIGHT = 2;
    // Use this for initialization
    void Start () {
            }
   
    // Update is called once per frame
    void Update () {
        if (Input.GetKeyDown(KeyCode.W)) {
            dir = UP;
           
        } else if (Input.GetKeyDown(KeyCode.S)) {
            dir = DOWN;
        } else if (Input.GetKeyDown(KeyCode.A)) {
            dir = LEFT;
           
        } else if (Input.GetKeyDown(KeyCode.D)) {
            dir = RIGHT;
        } else if (Input.GetKeyUp(KeyCode.W) | Input.GetKeyUp(KeyCode.S) | Input.GetKeyUp(KeyCode.A) | Input.GetKeyUp(KeyCode.D)) {
            dir = 0;
        }
       
        if (Input.GetKeyDown(KeyCode.Q)) {
            rot = RLEFT;
        } else if (Input.GetKeyDown(KeyCode.E)) {
            rot = RRIGHT;
        } else if (Input.GetKeyUp(KeyCode.Q) | Input.GetKeyUp(KeyCode.E)) {
            rot    = 0;
        }       
       
        //camera scroll
        if (dir==UP) {
            transform.Translate(0,0,5*Time.deltaTime);
        } else if (dir==DOWN) {
            transform.Translate(0,0,-5*Time.deltaTime);
        } else if (dir==LEFT) {
            transform.Translate(-5*Time.deltaTime,0,0);               
        } else if (dir==RIGHT) {       
            transform.Translate(5*Time.deltaTime,0,0);       
        }
        //camera rotation
        if (rot == RLEFT ) {
            transform.Rotate(0,25*Time.deltaTime,0);
            transform.LookAt(transform.position);
        } else if (rot == RRIGHT ) {
            transform.Rotate(0,-25*Time.deltaTime,0);
            transform.LookAt(transform.position);
        }            

             
    }
}

El gran problema de mi primera versión era que la vista no rotaba alrededor de un punto, o mejor dicho, sí lo hacía, pero no mirando al centro. Y es que crear la cámara como hija del GameObject objetivo no garantiza que la cámara se mantenga enfocada en el mismo, de ahí que a cada rotación haya que agregarle un transform.LookAt(transform.position); para mantenerla mirando al centro. Como siempre, esto ha sido resultado de mucho ensayo y error, así que ni es la mejor solución y hay cosas que no sé por qué o cómo funcionan. De todas formas espero que les sirva de ayuda si se deciden a programar un reboot de Fallout 2.

No hay comentarios:

Publicar un comentario en la entrada