I have got the pinch to zoom in and out working but I am having trouble with the pan. I want to detect the bounds of a sprite “Background” and make sure the camera is clamped so that the background never leaves the field of view of the camera. Here is what I have come up with.
using UnityEngine;
using System.Collections;
public class PinchZoom2 : MonoBehaviour {
private float orthoZoomSpeed = 0.25f; // The rate of change of the orthographic size in orthographic mode.
private float orthoCamSize;
private Vector3 camPos;
private float maxZoom;
private float minZoom = 2;
private float panSpeed = -0.1f;
public static bool isPanning; // Is the camera being panned?
Vector3 bottomLeft;
Vector3 topRight;
float cameraMaxY;
float cameraMinY;
float cameraMaxX;
float cameraMinX;
void Start()
{
isPanning = false;
maxZoom = Camera.main.orthographicSize;
orthoCamSize = maxZoom;
camPos = Camera.main.transform.position;
//set max camera bounds (assumes camera is max zoom and centered on Start)
topRight = camera.ScreenToWorldPoint(new Vector3(camera.pixelWidth, camera.pixelHeight, -transform.position.z));
bottomLeft = camera.ScreenToWorldPoint(new Vector3(0,0,-transform.position.z));
cameraMaxX = topRight.x;
cameraMaxY = topRight.y;
cameraMinX = bottomLeft.x;
cameraMinY = bottomLeft.y;
}
void Update ()
{
#if UNITY_EDITOR
//click and drag
if(Input.GetMouseButton(0)){
float x = Input.GetAxis("Mouse X") * panSpeed;
float y = Input.GetAxis("Mouse Y") * panSpeed;
transform.Translate(x,y,0);
}
#endif
// One Finger Pan
if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved){
isPanning = true;
// Touch touchZero = Input.GetTouch(0);
// float x = touchZero.position.x * panSpeed;
// float y = touchZero.position.y * panSpeed;
float x = Input.GetAxis("Mouse X") * panSpeed;
float y = Input.GetAxis("Mouse Y") * panSpeed;
transform.Translate(x,y,0);
isPanning = false;
}
#if UNITY_EDITOR
//zoom
if((Input.GetAxis("Mouse ScrollWheel") > 0) && Camera.main.orthographicSize > minZoom ) // forward
{
Camera.main.orthographicSize = Camera.main.orthographicSize - orthoZoomSpeed;
}
if ((Input.GetAxis("Mouse ScrollWheel") < 0) && Camera.main.orthographicSize < maxZoom) // back
{
Camera.main.orthographicSize = Camera.main.orthographicSize + orthoZoomSpeed;
}
#endif
// 2 finger Zoom
if (Input.touchCount == 2){
// Store both touches.
Touch touchZero = Input.GetTouch(0);
Touch touchOne = Input.GetTouch(1);
// Find the position in the previous frame of each touch.
Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;
// Find the magnitude of the vector (the distance) between the touches in each frame.
float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude;
float touchDeltaMag = (touchZero.position - touchOne.position).magnitude;
// Find the difference in the distances between each frame.
float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag;
// If the camera is orthographic...
if (camera.isOrthoGraphic)
{
// ... change the orthographic size based on the change in distance between the touches.
camera.orthographicSize += deltaMagnitudeDiff * orthoZoomSpeed;
// Make sure the orthographic size never drops below zero.
camera.orthographicSize = Mathf.Max(camera.orthographicSize, minZoom);
// Make sure the orthographic size never goes above original size.
camera.orthographicSize = Mathf.Min(camera.orthographicSize, maxZoom);
}
}
// On double tap image will be set at original position and scale
else if(Input.touchCount==1 && Input.GetTouch(0).phase == TouchPhase.Began && Input.GetTouch(0).tapCount==2)
{
camera.orthographicSize = orthoCamSize;
Camera.main.transform.position = camPos;
}
//check if camera is out-of-bounds, if so, move back in-bounds
topRight = camera.ScreenToWorldPoint(new Vector3(camera.pixelWidth, camera.pixelHeight, -transform.position.z));
bottomLeft = camera.ScreenToWorldPoint(new Vector3(0,0,-transform.position.z));
if(topRight.x > cameraMaxX)
{
transform.position = new Vector3(transform.position.x - (topRight.x - cameraMaxX), transform.position.y, transform.position.z);
}
if(topRight.y > cameraMaxY)
{
transform.position = new Vector3(transform.position.x, transform.position.y - (topRight.y - cameraMaxY), transform.position.z);
}
if(bottomLeft.x < cameraMinX)
{
transform.position = new Vector3(transform.position.x + (cameraMinX - bottomLeft.x), transform.position.y, transform.position.z);
}
if(bottomLeft.y < cameraMinY)
{
transform.position = new Vector3(transform.position.x, transform.position.y + (cameraMinY - bottomLeft.y), transform.position.z);
}
if (Input.GetKeyDown(KeyCode.Escape)) {
Application.Quit();
}
}
}
I have got everything working in the editor but on android the panning isn’t working as intended.
#if UNITY_EDITOR
//click and drag
if(Input.GetMouseButton(0)){
float x = Input.GetAxis("Mouse X") * panSpeed;
float y = Input.GetAxis("Mouse Y") * panSpeed;
transform.Translate(x,y,0);
}
#endif
// One Finger Pan
if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Began){
// Touch touchZero = Input.GetTouch(0);
// float x = touchZero.position.x * panSpeed;
// float y = touchZero.position.y * panSpeed;
float x = Input.GetAxis("Mouse X") * panSpeed;
float y = Input.GetAxis("Mouse Y") * panSpeed;
transform.Translate(x,y,0);
}
On android when you touch any spot on the screen while zoomed in it jumps to that spot. How do you detect when a finger is down and has moved? I wanted to be able to tap and drag my finger to pan up, down, left, right.
Now my only problem is on calculating camera bounds. It calculates correctly but it does not take into account my side menu which takes up 19.53% of the width. I am calculating camera bounds with this
//set max camera bounds (assumes camera is max zoom and centered on Start)
topRight = camera.ScreenToWorldPoint(new Vector3(camera.pixelWidth, camera.pixelHeight, -transform.position.z));
bottomLeft = camera.ScreenToWorldPoint(new Vector3(0,0,-transform.position.z));
cameraMaxX = topRight.x;
cameraMaxY = topRight.y;
cameraMinX = bottomLeft.x;
cameraMinY = bottomLeft.y;
Then on Update
//check if camera is out-of-bounds, if so, move back in-bounds
topRight = camera.ScreenToWorldPoint(new Vector3(camera.pixelWidth, camera.pixelHeight, -transform.position.z));
bottomLeft = camera.ScreenToWorldPoint(new Vector3(0,0,-transform.position.z));
if(topRight.x > cameraMaxX)
{
transform.position = new Vector3(transform.position.x - (topRight.x - cameraMaxX), transform.position.y, transform.position.z);
}
if(topRight.y > cameraMaxY)
{
transform.position = new Vector3(transform.position.x, transform.position.y - (topRight.y - cameraMaxY), transform.position.z);
}
if(bottomLeft.x < cameraMinX)
{
transform.position = new Vector3(transform.position.x + (cameraMinX - bottomLeft.x), transform.position.y, transform.position.z);
}
if(bottomLeft.y < cameraMinY)
{
transform.position = new Vector3(transform.position.x, transform.position.y + (cameraMinY - bottomLeft.y), transform.position.z);
}
Do you mean that the side the menu is on (left or right, by the way?) hides a part of your map?
If so, all you need to do is to add/substract (depending on which side it is) the menu size from your minX/maxX (still depending on the side).
If your menu if top or bottom, it’s the same, but with the Y coordinates.
As a note, you might want to calculate the menu size in pixels for this, it will make the calculations a bit smoother (rather than taking the window’s size and dividing it every time).
I think I don’t totally understand your problem, (even though I see potential other problems in your Update code), so I’ll either let someone else have a try at it, or ask for a screen shot of the problem.
Screen shot before I press play. Notice the right hand side of the screen is blue. Once I hit play the side menu gets drawn. I just need to find a way to subtract the width of the side menu from cameraMaxX bounds. Let me know if you have any more questions.
Also the side menu script is not attached to the main camera unlike the pinch to zoom script above.
You should not create a complete Vector3 in each IF, but only modify the relevant value (‘.x’ or ‘.y’).
It doesn’t make much difference, but when both X and Y are out of bounds, you will take 2 frames to correct it instead of 1.
Apart from this, it’s nice that you managed to solve it.