Translate using local space to center Camera on gameObject

Hi All,

I have a camera that is rotated 45 degrees on both the x and y axis, as we are working on an isometric game. That camera is looking at some cubes.

I want to make my camera smooth pan using lerp to whatever direction is required in order to center on a gameObject that is being passed in.

When panning right now, I translate using space.self in order to preserve our isometric rotation. I don’t want rotate the camera, as that would break our isometric view, so using the lookat function is out.

I already use panning with right click and dragging that uses space.self, but I haven’t been able to apply that to this idea.

I’ve looked at the question below and believe I must need to create a plane that is also working on the same angle as my camera.

Here is my current script. It wont be too cohesive at the moment as I’ve merged a bunch of different scripts to get the functionality I want.

Can someone please point me in the right direction? :slight_smile:

using UnityEngine;


public class DynoCam : MonoBehaviour
{
    public static DynoCam instance;

    public float PanSpeed = 1;
    public int speed = 3;
    private Vector3 dragOrigin;

    Vector3 startPos;

    public bool cameraDragging = true;
    public bool CanDoCameraStuff = true;

    float outerLeft = -20f;
    float outerRight = 2f;
    float outerUp = 45f;
    float outerDown = 15f;


    float zoomSensitivity = 15.0f;
    float zoomSpeed = 2.0f;
    float zoomMin = 3.0f;
    float zoomMax = 30.0f;

    private float zoom;

    public Camera selectedCamera;
    public float MINSCALE = 2.0F;
    public float MAXSCALE = 5.0F;
    public float varianceInDistances = 5.0F;
    private float touchDelta = 0.0F;
    private Vector2 prevDist = new Vector2(0, 0);
    private Vector2 curDist = new Vector2(0, 0);
    private float startAngleBetweenTouches = 0.0F;
    private int vertOrHorzOrientation = 0;
    private Vector2 midPoint = new Vector2(0, 0);

   


    void Start()
    {
        if (instance == null)
            instance = this;
        else
            Destroy(this);

        startPos = transform.position;
        selectedCamera = Camera.main;
        zoom = Camera.main.orthographicSize;
        if (Application.platform != RuntimePlatform.Android && Application.platform != RuntimePlatform.IPhonePlayer)
        {
            zoom = Camera.main.orthographicSize * 1.5f;
        }
    }

    public void ResetCameraPosition()
    {
        transform.position = startPos;// GetCenteredCameraPos();
        Camera.main.orthographicSize = 3;
        Camera cam;
        Plane[] planes;
        cam = Camera.main;

        int loopProtection;
        foreach (GameObject G in generateLevel.instance.LandMass)
        {
            loopProtection = 0;
            while (true)
            {

                planes = GeometryUtility.CalculateFrustumPlanes(cam);
                //if (!GeometryUtility.TestPlanesAABB(planes, anObjCollider.bounds))
                if (!GeometryUtility.TestPlanesAABB(planes, G.GetComponent<GridTile>().HeldBlock.GetComponent<Collider>().bounds))
                {
                    cam.orthographicSize += 0.5f;

                }
                else
                {
                    break;
                }
                loopProtection++;
                if (loopProtection > 15)
                    break;
            }

        }

        cam.orthographicSize += 3.5f;
        cam.orthographicSize = Mathf.Clamp(cam.orthographicSize, 5, 40);
    }

    private Vector3 GetCenteredCameraPos()
    {

        float x = 0f;
        float y = 0f;
        float z = 0f;
        foreach (GameObject pos in generateLevel.instance.LandMass)
        {
            x += pos.transform.position.x;
            y += pos.transform.position.y;
            z += pos.transform.position.z;
        }
        return new Vector3(x / generateLevel.instance.LandMass.Count, y / generateLevel.instance.LandMass.Count, z / generateLevel.instance.LandMass.Count);
    }
    

    void Update()
    {

        if (CanDoCameraStuff)
            if (GameManager.instance.CurrentState == GameState.Play)
            {
                //
                //  if pc version
                //
                if (Application.platform != RuntimePlatform.Android && Application.platform != RuntimePlatform.IPhonePlayer)
                {
                    zoom -= Input.GetAxis("Mouse ScrollWheel") * zoomSensitivity;
                    zoom = Mathf.Clamp(zoom, zoomMin, zoomMax);
                }

                //
                //  if mobile version
                //
                else
                {

                    if (!GodController.instance.ClickedOnTile)
                    {
                        //if (Input.touchCount != 0)
                        //   
                        if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved)
                        {
                            //Debug.Log(Input.touchCount);
                            Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
                            float panSpeedMobile = 1f * Time.deltaTime;
                            Vector3 lerpToPos = new Vector3(-touchDeltaPosition.x * panSpeedMobile, -touchDeltaPosition.y * panSpeedMobile, 0);

                            transform.Translate(-touchDeltaPosition.x * panSpeedMobile, -touchDeltaPosition.y * panSpeedMobile, 0);
                            //transform.position = Vector3.Lerp(transform.position, transform.position + lerpToPos, Time.deltaTime * panSpeedMobile);

                        }
                        else if (Input.touchCount == 2 && Input.GetTouch(0).phase == TouchPhase.Moved && Input.GetTouch(1).phase == TouchPhase.Moved)
                        {


                            midPoint = new Vector2(((Input.GetTouch(0).position.x + Input.GetTouch(1).position.x) / 2), ((Input.GetTouch(0).position.y - Input.GetTouch(1).position.y) / 2)); //store midpoint from first touches
                            curDist = Input.GetTouch(0).position - Input.GetTouch(1).position; //current distance between finger touches
                            prevDist = ((Input.GetTouch(0).position - Input.GetTouch(0).deltaPosition) - (Input.GetTouch(1).position - Input.GetTouch(1).deltaPosition)); //difference in previous locations using delta positions
                            touchDelta = curDist.magnitude - prevDist.magnitude;

                            if ((Input.GetTouch(0).position.x - Input.GetTouch(1).position.x) > (Input.GetTouch(0).position.y - Input.GetTouch(1).position.y))
                            {
                                vertOrHorzOrientation = -1;
                            }
                            if ((Input.GetTouch(0).position.x - Input.GetTouch(1).position.x) < (Input.GetTouch(0).position.y - Input.GetTouch(1).position.y))
                            {
                                vertOrHorzOrientation = 1;
                            }

                            if ((touchDelta < 0)) //
                            {
                                zoom = Mathf.Clamp(Camera.main.orthographicSize + (1 * speed), zoomMin, zoomMax);
                            }


                            if ((touchDelta > 0))

                            {
                                zoom = Mathf.Clamp(Camera.main.orthographicSize - (1 * speed), zoomMin, zoomMax);
                            }

                        }
                        Camera.main.orthographicSize = Mathf.Clamp(Camera.main.orthographicSize, zoomMin, zoomMax);

                    }
                }
            }
    }

    void LateUpdate()
    {

        if (GameManager.instance.CurrentState == GameState.Play)
        {

            Camera.main.orthographicSize = Mathf.Lerp(Camera.main.orthographicSize, zoom, Time.deltaTime * zoomSpeed);


            //
            //  if pc version
            //
            if (Application.platform != RuntimePlatform.Android && Application.platform != RuntimePlatform.IPhonePlayer)
            {
                Vector2 mousePosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);

                float left = Screen.width * 0.2f;
                float right = Screen.width - (Screen.width * 0.2f);

                if (mousePosition.x < left)
                {
                    cameraDragging = true;
                }
                else if (mousePosition.x > right)
                {
                    cameraDragging = true;
                }

                if (cameraDragging)
                {
                    if (Input.GetMouseButtonDown(1))
                    {
                        dragOrigin = Input.mousePosition;
                        return;
                    }

                    if (!Input.GetMouseButton(1)) return;

                    Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - dragOrigin);
                    Vector3 moveX = new Vector3(pos.x * PanSpeed, 0, 0);
                    Vector3 moveY = new Vector3(0, pos.y * PanSpeed, 0);

                    if (moveX.x > 0f)
                    {
                        if (this.transform.position.x < outerRight)
                        {
                            transform.Translate(moveX, Space.Self);
                            
                        }
                    }
                    else
                    {
                        if (this.transform.position.x > outerLeft)
                        {
                            transform.Translate(moveX, Space.Self);
                        }
                    }
                    if (moveY.y > 0f)
                    {
                        if (this.transform.position.y < outerUp)
                        {
                            transform.Translate(moveY, Space.Self);
                        }
                    }
                    else
                    {
                        if (this.transform.position.y > outerDown)
                        {
                            transform.Translate(moveY, Space.Self);
                        }
                    }
                }

            }

            //
            //  if mobile version
            //
            else
            {

            }
        }
    }
}

on click, you could send a Raycast from your camera through the middle of the screen onto the object plane ( i assume that every tile of your game exists at the same height? like y = 0 for example? so you would create an invisible plane with a collider and chose raycast as gameobject.layer (has to be created), your raycast uses then the raycast-layermask)

this gives you the position you are currently looking on, now you get the position from the object you clicked on and substract your viewposition from it.

the result is a translation-vector that should do the trick. simply add the vector to your camera position.

You can make the camera a child of an empty game object (let’s call it beam). This beam should always stay at ground level. Then you can lerp the position of the beam to your wanted position and the camera will follow while keeping its rotation (but make sure the camera is actually looking at the beam). I’m using the same technique here: - YouTube