Unity:如何限制相机的缩小

时间:2019-01-16 02:44:08

标签: unity3d

使用Unity 2018.3

此摄像机脚本允许用户放大和缩小并通过触摸来移动摄像机。

Start()上,脚本获取摄像机的当前位置,并将其保存为越界限制。因此,如果播放器放大并且将相机移到侧面,则在达到界限时相机将停止。

我的问题是,当前用户可以缩小自己想要的所有内容,导致脚本摇晃,因为脚本试图重新定位相机,但这并不能阻止用户增加orthographicSize

如何限制用户进行缩小操作,使其越过Start()上的超出范围限制?

public class ControlCamera : MonoBehaviour
{

    private Vector2?[] oldTouchPositions = {
        null,
        null
    };

    private Vector2 oldTouchVector;

    private float oldTouchDistance;

    private Vector3 bottomLeft;
    private Vector3 topRight;

    private float cameraMaxY;
    private float cameraMinY;
    private float cameraMaxX;
    private float cameraMinX;

    public float maxZoom;
    public float minZoom;

    private void Start()
    {
        //  Set max camera bounds
        topRight = GetComponent<Camera>().ScreenToWorldPoint(new Vector3(GetComponent<Camera>().pixelWidth, GetComponent<Camera>().pixelHeight, -transform.position.z));
        bottomLeft = GetComponent<Camera>().ScreenToWorldPoint(new Vector3(0, 0, -transform.position.z));
        cameraMaxX = topRight.x;
        cameraMaxY = topRight.y;
        cameraMinX = bottomLeft.x;
        cameraMinY = bottomLeft.y;
    }

    private void Update()
    {
        //  No touches
        if (Input.touchCount == 0)
        {
            oldTouchPositions[0] = null;
            oldTouchPositions[1] = null;
        }
        //  1 Touch
        else if (Input.touchCount == 1)
        {
            if (oldTouchPositions[0] == null || oldTouchPositions[1] != null)
            {
                oldTouchPositions[0] = Input.GetTouch(0).position;
                oldTouchPositions[1] = null;
            }
            else
            {
                Vector2 newTouchPosition = Input.GetTouch(0).position;

                transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] - newTouchPosition) * GetComponent<Camera>().orthographicSize / GetComponent<Camera>().pixelHeight * 2f));

                oldTouchPositions[0] = newTouchPosition;
            }
            //  2 touches or more
        } else {

            if (oldTouchPositions[1] == null)
            {
                oldTouchPositions[0] = Input.GetTouch(0).position;
                oldTouchPositions[1] = Input.GetTouch(1).position;
                oldTouchVector = (Vector2)(oldTouchPositions[0] - oldTouchPositions[1]);
                oldTouchDistance = oldTouchVector.magnitude;

            } else {

                Vector2 screen = new Vector2(GetComponent<Camera>().pixelWidth, GetComponent<Camera>().pixelHeight);

                Vector2[] newTouchPositions = {
                    Input.GetTouch(0).position,
                    Input.GetTouch(1).position
                };
                Vector2 newTouchVector = newTouchPositions[0] - newTouchPositions[1];
                float newTouchDistance = newTouchVector.magnitude;

                transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] + oldTouchPositions[1] - screen) * GetComponent<Camera>().orthographicSize / screen.y));
                GetComponent<Camera>().orthographicSize *= oldTouchDistance / newTouchDistance;
                transform.position -= transform.TransformDirection((newTouchPositions[0] + newTouchPositions[1] - screen) * GetComponent<Camera>().orthographicSize / screen.y);

                oldTouchPositions[0] = newTouchPositions[0];
                oldTouchPositions[1] = newTouchPositions[1];
                oldTouchVector = newTouchVector;
                oldTouchDistance = newTouchDistance;

                // --------------------------------------------------------------->>

                //  Control Zoom In
                if (GetComponent<Camera>().orthographicSize > minZoom)
                {
                    //
                }

                //  Control Zoom Out
                if (GetComponent<Camera>().orthographicSize < maxZoom)
                {
                    //
                }

                // --------------------------------------------------------------->>
            }
        }

        //  Check if camera is out-of-bounds, if so, move back in-bounds
        topRight = GetComponent<Camera>().ScreenToWorldPoint(new Vector3(GetComponent<Camera>().pixelWidth, GetComponent<Camera>().pixelHeight, -transform.position.z));
        bottomLeft = GetComponent<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);
        }
    }
}

1 个答案:

答案 0 :(得分:3)

  1. 您不应重复使用GetComponent,尤其是在Update或任何重复调用的方法中,因为这会产生很多不必要的开销。而是一次获得它

    private Camera camera;
    
    private void Awake()
    {
        camera = GetComponent<Camera>();
    }
    

    并重用该引用->到处替换GetComponent<Camera>()宽度camera

  2. 如果我的理解正确,orthographicSize就是相机高度的一半(以世界单位为单位)。

    由于您已经获得了topRightbottomLeft的世界坐标,因此您应该能够计算出orthographicSize

    maxZoom = (CameraMaxY - CameraMinY) / 2.0f;
    

    但是,无论如何,如果您希望原始缩放为最大缩放,则也可以像这样存储原始缩放

    maxZoom = camera.orthographicSize;
    
  3. 然后您可以简单地clamp这样的值

    camera.orthographicSize = Mathf.Clamp(
        camera.orthographicSize * oldTouchDistance / newTouchDistance, 
        minZoom, 
        maxZoom);
    

    ->无需额外的if检查