Unity: как ограничить масштабирование камеры - PullRequest
0 голосов
/ 16 января 2019

Использование 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 голосов
/ 16 января 2019
  1. Вы не должны использовать GetComponent несколько раз, особенно в Update или любом повторно вызываемом методе, поскольку это создает много ненужных накладных расходов. Вместо этого получите это однажды

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

    и повторно использовать эту ссылку -> Везде заменить GetComponent<Camera>() ширина camera

  2. Если мое понимание верно, orthographicSize - это половина высоты камеры в мировых единицах.

    Поскольку вы уже получаете topRight и bottomLeft в мировых координатах, вы сможете рассчитать orthographicSize

    maxZoom = (CameraMaxY - CameraMinY) / 2.0f;
    

    однако, если в любом случае вы хотите, чтобы исходное увеличение было максимальным, можно также просто сохранить исходное увеличение, например

    maxZoom = camera.orthographicSize;
    
  3. И позже вы можете просто зажать значение как

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

    -> нет необходимости в дополнительных if чеках

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...