Rodney Foley Rodney Foley - 1 month ago 22
C# Question

Move Camera Over Terrain Using Touch Input in Unity 3D

I am new to Unity and I am trying to figure out how to move the camera over a map/terrain using touch input. The camera would be looking down at the terrain with a rotation of (90,0,0). The terrain is on layer 8. I have had no problem getting it moving with keyboard, now I am trying to move to touch and it is very different if you want to keep expected usage on iOS.

The best example I can think of on a built in iOS app is Maps where the user would touch the screen and that point on the map would stay under the finger as long as the finger stayed on the screen. So as the user moves their finger the map appears to be moving with the finger. I have not been able to find examples that show how to do it this way. I have seen may examples of moving the camera or character with the mouse but they don't seem to translate well to this style.

Also posted on Unity3D Answers:

http://answers.unity3d.com/questions/283159/move-camera-over-terrain-using-touch-input.html

Answer

Below should be what you need. Note that it's tricky to get a 1 to 1 correspondence between finger/cursor and the terrain when using a "perspective" camera. If you change you camera to orthographic, the script below should give you a perfect map between finger/cursor position and map movement. With "perspective" you'll notice a slight offset.

You could also do this with ray tracing but I've found that route to be sloppy and not as intuitive.

Camera settings for testing (values are pulled from the inspector so apply them there):

  1. Position: 0,20,0
  2. Orientation: 90,0,0
  3. Projection: Perspective/Orthographic

using UnityEngine;
using System.Collections;

public class ViewDrag : MonoBehaviour {
Vector3 hit_position = Vector3.zero;
Vector3 current_position = Vector3.zero;
Vector3 camera_position = Vector3.zero;
float z = 0.0f;

// Use this for initialization
void Start () {

}

void Update(){
    if(Input.GetMouseButtonDown(0)){
        hit_position = Input.mousePosition;
        camera_position = transform.position;

    }
    if(Input.GetMouseButton(0)){
        current_position = Input.mousePosition;
        LeftMouseDrag();        
    }
}

void LeftMouseDrag(){
    // From the Unity3D docs: "The z position is in world units from the camera."  In my case I'm using the y-axis as height
    // with my camera facing back down the y-axis.  You can ignore this when the camera is orthograhic.
    current_position.z = hit_position.z = camera_position.y;

    // Get direction of movement.  (Note: Don't normalize, the magnitude of change is going to be Vector3.Distance(current_position-hit_position)
    // anyways.  
    Vector3 direction = Camera.main.ScreenToWorldPoint(current_position) - Camera.main.ScreenToWorldPoint(hit_position);

    // Invert direction to that terrain appears to move with the mouse.
    direction = direction * -1;

    Vector3 position = camera_position + direction;

    transform.position = position;
}
}