Wednesday, May 6, 2015

Unity3d isometric camera tutorial

I had pending this since a month ago, so Im forcing myself to post it today. The goal is to provide a fully functional isometric like system that you can use with few or none modifications in your own game. So, lets get started.

Start Unity3d and in your scene, add an empty GameObject, we will call it target. Create a camera object and drag it to target to make it child. The result looks like this:


Now select Camera and set the values to this:


For a true isometric like feeling, ortho projection is essential. You could use perspective, but it is not the same. Play with Size to suit your needs (we will be using this later, when implementing zoom).

Now, lets create an script named CameraController, or whatever, and drag it to target GameObject. Lets implement scrolling, the easier part: go to Update() and add the following code:

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;
        }

// and here is the actual camera scroll
        if (dir==UP) {
                         transform.Translate(0,0,20*Time.deltaTime);
        } else if (dir==DOWN) {
                          transform.Translate(0,0,-20*Time.deltaTime);
        } else if (dir==LEFT) {
                         transform.Translate(-20*Time.deltaTime,0,0);               
        } else if (dir==RIGHT) {   
                          transform.Translate(20*Time.deltaTime,0,0);       
        }

Done, we already have a very basic scrolling! The idea is to detect the key down event, set a variable and start scrolling until the key release is detected. Now, lets add mouse scrolling, which is very simple too, we want that the camera scrolls when the mouse cursor reaches the screen edges:

//mouse scroll
        if (Input.mousePosition.x >= Screen.width - 10 ) {
            //scroll right
            transform.Translate (20*Time.deltaTime,0,0);
        } else if (Input.mousePosition.x <= 10 && transform.position.x>10) {
            transform.Translate(-20*Time.deltaTime,0,0);
        }

        if (Input.mousePosition.y >= Screen.height - 10 && transform.position.z>10) {
            transform.Translate (0,0,20*Time.deltaTime);
        } else if (Input.mousePosition.y <= 10 ) {
            transform.Translate(0,0,-20*Time.deltaTime);
        }

Looks easy, isnt it? Now, lets make it better by adding rotation using middle mouse.

//camera rotation with middle mouse
        if (Input.GetMouseButton(2)) {
                if(Input.GetAxis("Mouse X")>0) {
                    //moving left
                    transform.Rotate(0,45*Time.deltaTime,0);
                    transform.LookAt(transform.position);
                    }
                if(Input.GetAxis("Mouse X")<0) {
                    transform.Rotate(0,-45*Time.deltaTime,0);
                    transform.LookAt(transform.position);
                    }
                }

And using keys is trivial too, lets use Q and R to rotate the view:

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;
        }

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);
        }

So far we havea quite complete system, yet, we can add a couple of details more, like zoom, via mouse wheel.

// Mouse wheel zoom in/out
        if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {
            if (Camera.main.fieldOfView<=125)
                Camera.main.fieldOfView +=2;
            if (Camera.main.orthographicSize<=19)
                Camera.main.orthographicSize +=0.5f;
           
        }

        if (Input.GetAxis("Mouse ScrollWheel") > 0)
        {
            if (Camera.main.fieldOfView>2)
                Camera.main.fieldOfView -=2;
            if (Camera.main.orthographicSize>=8)
                Camera.main.orthographicSize -=0.5f;
        }

Done! Now the isometric view is complete with scrolling, rotation and zoom. But we still can add a little trick: the camera should not go beyond scene limits. I will show you a simple solution based on terrain: by calculating the terrain size, you can prevent the camera from moving beyond the terrain borders. Go to Start() and add this code:

GameObject go = GameObject.FindGameObjectWithTag ("Terrain");
tsize = go.GetComponent<Terrain>().terrainData.size;   

HEre we take the terrain object and get its size, storing it in a class member tsize of type Vector3. Now we modify the scrolling code like this:

if (dir==UP) {
            if (transform.position.z<tsize.z-10)    //is inside terrain border?
                transform.Translate(0,0,20*Time.deltaTime);
        } else if (dir==DOWN) {
            if (transform.position.z>10)    //is inside terrain border?
                transform.Translate(0,0,-20*Time.deltaTime);
        } else if (dir==LEFT) {
            if (transform.position.x>10)    //is inside terrain border?
                transform.Translate(-20*Time.deltaTime,0,0);               
        } else if (dir==RIGHT) {   
            if (transform.position.x<tsize.x-10)    //is inside terrain border?
                transform.Translate(20*Time.deltaTime,0,0);       
        }

Fix the mouse scrolling method too, and your system is really complete. This is all, hope it works for you, and remember you can get the code from our github repo.

No comments:

Post a Comment