0

I'm trying to limit the zoom value of my game to a minimum and a maximum but i can't get how to do it! I've been trying by limiting the Y according to the zoom factor but it does not work properly, because when it reaches the limit, it starts flickering, like it hit an obstacle. I found some things that can solve this problem by using the fieldofview, but I need it to work with the Y limitations! I also want to add a panning limit, so that the player won't be able to see the end of the map but I didn't get there yet.

Anyways, here is the code i'm using and would appreciate if someone could help!

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

class ScrollAndPinch : MonoBehaviour
{
#if UNITY_IOS || UNITY_ANDROID
  public Camera Camera;
  public bool Rotate;
  protected Plane Plane;

  public float scrollSpeed;
  public float rotateSpeed;
  public float zoomSpeed;

  public float zoomMinY;
  public float zoomMaxY;

  public float camsummer;

  Vector3 pos;
  private Vector3 velocity = Vector3.zero;


  private void Awake()
  {
    if (Camera == null)
      Camera = Camera.main;

    Rotate = true;

    scrollSpeed = 50f;
    rotateSpeed = 50f;
    zoomSpeed = 1f;

    zoomMinY = 50f;
    zoomMaxY = 200f;

    camsummer = 0.1f;

    pos = new Vector3(0f, 0f, 0f);

  }

  private void Update()
  {

    //Update Plane
    if (Input.touchCount >= 1)
      Plane.SetNormalAndPosition(transform.up, transform.position);

    var Delta1 = Vector3.zero;
    var Delta2 = Vector3.zero;

    //Scroll
    if (Input.touchCount == 1)
    {
      Delta1 = PlanePositionDelta(Input.GetTouch(0));
      if (Input.GetTouch(0).phase == TouchPhase.Moved)
        Camera.transform.Translate(Delta1 * scrollSpeed * Time.deltaTime, Space.World);
    }

    //Pinch
    if (Input.touchCount == 2)
    {
      var pos1 = PlanePosition(Input.GetTouch(0).position);
      var pos2 = PlanePosition(Input.GetTouch(1).position);
      var pos1b = PlanePosition(Input.GetTouch(0).position - Input.GetTouch(0).deltaPosition);
      var pos2b = PlanePosition(Input.GetTouch(1).position - Input.GetTouch(1).deltaPosition);

      //calc zoom to be done relative to the distance moved between the fingers
      var zoom = (Vector3.Distance(pos1, pos2) /
                 Vector3.Distance(pos1b, pos2b));

      //edge case (Bad calculation)
      if (zoom == 0 || zoom > 10)
        return;

      //Move cam amount the mid ray. This is where the zoom is applied

      // Vector3 pos = Camera.transform.position;
      // pos.y = Mathf.Clamp(pos.y, zoomMinY, zoomMaxY);
      // Camera.transform.position = Vector3.Lerp(pos1, Camera.transform.position, (1 / zoom));
      // Camera.transform.position = pos;



      if (Camera.transform.position.y < zoomMinY | Camera.transform.position.y > zoomMaxY)
      {
        // Camera.transform.position = pos;
        Camera.transform.position = Vector3.SmoothDamp(Camera.transform.position, pos, ref velocity, camsummer);
        // Camera.transform.position = Vector3.LerpUnclamped(Camera.transform.position, pos, camsummer);
        // for (int i = 0; i < 1000; i++)
        // {
        // }

      }
      else if (Camera.transform.position.y >= zoomMinY && Camera.transform.position.y <= zoomMaxY)
      {
        pos = Camera.transform.position;
        Camera.transform.position = Vector3.LerpUnclamped(pos1, Camera.transform.position, (1 / zoom));
        //This is where the rotation is applied
        if (Rotate && pos2b != pos2)
          Camera.transform.RotateAround(pos1, Plane.normal,
            Vector3.SignedAngle(pos2 - pos1, pos2b - pos1b, Plane.normal) * rotateSpeed * Time.deltaTime);
      }
      // pos.y = zoomMinY;
    }



    // if (Camera.transform.position.y > 200)
    // {
    //   zoomMaxY.y = 200;
    //   Camera.transform.position = zoomMaxY;
    // }
    // else if (Camera.transform.position.y < 50)
    // {
    //   zoomMinY.y = 50;
    //   Camera.transform.position = zoomMinY;
    // }
    // else if (Camera.transform.position.y >= 50 && Camera.transform.position.y <= 200)
    // {
    //   Camera.transform.position = Vector3.LerpUnclamped(pos1, Camera.transform.position, (1 / zoom));
    // }


    // Vector3 Cam = Mathf.Clamp(Camera.transform.position.y, zoomMinY.y, zoomMaxY.y);


    // if (Camera.transform.position.y > zoomMaxY || Camera.transform.position.y < zoomMinY)
    // {
    //   Vector3 camLimit = Camera.transform.position;
    //   camLimit.y = Mathf.Clamp(Camera.transform.position.y, zoomMinY, zoomMaxY);
    //   Camera.transform.position = camLimit;



    //   // Vector3 camLimit = Camera.transform.position;
    //   // camLimit = (transform.position.);
    //   // Camera.transform.position = camLimit;
    // }
    // else if (Camera.transform.position.y >= zoomMinY && Camera.transform.position.y <= zoomMaxY)
    // {
    //   Camera.transform.position = Vector3.LerpUnclamped(pos1, Camera.transform.position, (1 / zoom));
    // }





  }

  protected Vector3 PlanePositionDelta(Touch touch)
  {
    //not moved
    if (touch.phase != TouchPhase.Moved)
      return Vector3.zero;

    //delta: How far have we moved from A to B by sliding the finger
    var rayBefore = Camera.ScreenPointToRay(touch.position - touch.deltaPosition);
    var rayNow = Camera.ScreenPointToRay(touch.position);
    if (Plane.Raycast(rayBefore, out var enterBefore) && Plane.Raycast(rayNow, out var enterNow))
      return rayBefore.GetPoint(enterBefore) - rayNow.GetPoint(enterNow);

    //not on plane
    return Vector3.zero;
  }

  protected Vector3 PlanePosition(Vector2 screenPos)
  {
    //position
    var rayNow = Camera.ScreenPointToRay(screenPos);
    if (Plane.Raycast(rayNow, out var enterNow))
      return rayNow.GetPoint(enterNow);

    return Vector3.zero;
  }

  private void OnDrawGizmos()
  {
    Gizmos.DrawLine(transform.position, transform.position + transform.up);
  }
#endif
}

And to make it easier to see, this is the part I am struggling to make it work.

if (Camera.transform.position.y < zoomMinY | Camera.transform.position.y > zoomMaxY)
      {
        Camera.transform.position = Vector3.SmoothDamp(Camera.transform.position, pos, ref velocity, camsummer);


      }
      else if (Camera.transform.position.y >= zoomMinY && Camera.transform.position.y <= zoomMaxY)
      {
        pos = Camera.transform.position;
        Camera.transform.position = Vector3.LerpUnclamped(pos1, Camera.transform.position, (1 / zoom));
        //This is where the rotation is applied
        if (Rotate && pos2b != pos2)
          Camera.transform.RotateAround(pos1, Plane.normal,
            Vector3.SignedAngle(pos2 - pos1, pos2b - pos1b, Plane.normal) * rotateSpeed * Time.deltaTime);
      }
Nicokam
  • 1
  • 2

1 Answers1

0

Does this happen when the camera gets close to an object? If so change the near clip plane distance on your camera to.near = 0

That should stop it from not showing the gameobject, if ur camera keeps moving it might cause the flickering because it clips in and out of the near clip plane

Bean5 Music
  • 179
  • 4
  • Thanks for your reply! No, it doesn't happen when the camera gets close to an object. I'm afraid your suggestion did not work in my case. Do you have any other possible ideas? – Nicokam Jun 17 '20 at 01:51
  • when the camera reaches the limit it might try to instantly go back to its old position, and than get updated to the new position again, this might cause it to trip out – Bean5 Music Jun 17 '20 at 11:15