Camera Points of Interest

Hey, I’m currently using the smooth look camera script: http://wiki.unity3d.com/index.php/SmoothMouseLook
and I was wondering if there’s a way to make the camera drawn towards points of interest.
As in if you move the camera near a certain object with the right script it would have a magnetic feel to it.

So far I’ve only been able to manage a hacked together hard look that’s still kinda glitchy:Code

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

public class CameraController : MonoBehaviour
{
    #region Fields

    // SETTINGS //
    public  float       sensitivityX     = 15f;
    public  float       sensitivityY     = 15f;

    // VARIABLES //
    private float       rotationX        = 0f;
    private float       rotationY        = 0f;
    private List<float> rotationArrayX   = new List<float>();
    private List<float> rotationArrayY   = new List<float>();
    private float       frameCounter     = 20f;
    private Quaternion  originalRotation;

    private Vector3     currentFocusPoint = Vector3.zero;

    [System.NonSerialized] public List<CameraFocusPoint> focusPoints = new List<CameraFocusPoint>();

    #endregion

    #region Unity Functions

    void Start()
    {
        originalRotation = transform.localRotation;
    }

    void Update()
    {
        currentFocusPoint = Vector3.zero;

        CalculateCameraFocusPoint();
        CalculateLerp();
    }

    #endregion

    #region Functions

    public void CalculateCameraFocusPoint()
    {
        // If the player is free looking
        if (Input.GetMouseButton(1))
        {
            // Check if there's any camera focus points in range.
            // Start by finding the nearest focus point to the mouse.
            float            nearestDistance = float.MaxValue;
            CameraFocusPoint nearestPoint    = null;
            foreach (CameraFocusPoint focusPoint in focusPoints)
            {
                Vector3 point    = Camera.main.WorldToScreenPoint(focusPoint.transform.position);
                float distance   = Vector2.Distance(point, new Vector2(Screen.width / 2, Screen.height / 2));

                if (point.z > 0 && distance < nearestDistance && distance < focusPoint.cameraFocusDistance)
                {
                    nearestDistance = distance;
                    nearestPoint    = focusPoint;
                }
            }

            if (nearestPoint != null) // FOCUSING //
            {
                currentFocusPoint = nearestPoint.transform.position;
            }
            else // NORMAL FREE LOOK //
            {
                rotationX += Input.GetAxis("Mouse X") * sensitivityX;
                rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
            }
        }
        else // Otherwise keep the camera normal.
        {
            rotationX = 0;
            rotationY = 0;
        }
    }

    public void CalculateLerp()
    {
        // If we don't have a focus point
        if (currentFocusPoint == Vector3.zero)
        {
            // Add it to the total.
            rotationArrayX.Add(rotationX);
            rotationArrayY.Add(rotationY);

            // Limit the collection.
            if (rotationArrayX.Count >= frameCounter)
            {
                rotationArrayX.RemoveAt(0);
            }

            if (rotationArrayY.Count >= frameCounter)
            {
                rotationArrayY.RemoveAt(0);
            }

            // Calculate the average rotation.
            float rotationAverageX = 0f;
            float rotationAverageY = 0f;

            for (int i = 0; i < rotationArrayX.Count; i++)
            {
                rotationAverageX += rotationArrayX[i];
            }

            for (int i = 0; i < rotationArrayY.Count; i++)
            {
                rotationAverageY += rotationArrayY[i];
            }

            rotationAverageX /= rotationArrayX.Count;
            rotationAverageY /= rotationArrayY.Count;
       
            Quaternion xQuaternion = Quaternion.AngleAxis(rotationAverageX, Vector3.up);
            Quaternion yQuaternion = Quaternion.AngleAxis(rotationAverageY, Vector3.left);

            transform.localRotation = originalRotation * xQuaternion * yQuaternion;
        }
        else // If we do.
        {
            transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(currentFocusPoint - transform.position), Time.deltaTime * 1);
        }
    }

    #endregion
}

Thanks in advance.

I’d do something where there are GameObjects around the scene that are positioned and oriented how the camera wants to be positioned from that point of interest.

I’d also have a Collider set up as a Trigger to enter into. Of course this trigger point may not be oriented the same as the camera itself if you’re using the player as the triggers for this. So it may have to be on a separate GameObject. I’d probably have the trigger region as one GameObject, and then the Camera position as a GameObject of it.

Then have a script on that Collider that listens for OnTriggerEnter and OnTriggerExit. When the agent enters the trigger region (test who it is in the OnTriggerEnter, or even use a custom layer that only collides with the agent/player). Grab a reference to the CameraController and pass in the camera position node as an override target position.

The CameraController should have two modes. 1 where it targets the agent/player, and another for targeting this point of interest. Both each just need 1 property each, both being the Transforms of interest.

In player mode it acts normally.

In point of interest mode it tweens the camera towards the position of being like the point of interest.

The player will need to be able to look at the point from multiple angles, it’s for a grappling hook system. So the camera would kind of stick to the point of interest a little bit, but the player would be a able to pull the camera away from it with a bit of extra effort.

Thanks for the suggestion though!

Maybe by getting the point of interests position in screen space, detecting how far away that point is from the center of the screen and using that value as a strength while easing the cameras rotation towards that point. The problem I’m stuck on is tying it into the rotation average system that’s currently going on in the code for the smooth look.

If I could find a way to get this bit code to point the rotationX and rotationY towards the point of interest instead of mouse input I’d be golden.

rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;