Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Camera Points of Interest

Discussion in 'Scripting' started by thekill473, Oct 22, 2015.

  1. thekill473

    thekill473

    Joined:
    Aug 26, 2012
    Posts:
    9
    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 (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class CameraController : MonoBehaviour
    6. {
    7.     #region Fields
    8.  
    9.     // SETTINGS //
    10.     public  float       sensitivityX     = 15f;
    11.     public  float       sensitivityY     = 15f;
    12.  
    13.     // VARIABLES //
    14.     private float       rotationX        = 0f;
    15.     private float       rotationY        = 0f;
    16.     private List<float> rotationArrayX   = new List<float>();
    17.     private List<float> rotationArrayY   = new List<float>();
    18.     private float       frameCounter     = 20f;
    19.     private Quaternion  originalRotation;
    20.  
    21.     private Vector3     currentFocusPoint = Vector3.zero;
    22.  
    23.     [System.NonSerialized] public List<CameraFocusPoint> focusPoints = new List<CameraFocusPoint>();
    24.  
    25.     #endregion
    26.  
    27.     #region Unity Functions
    28.  
    29.     void Start()
    30.     {
    31.         originalRotation = transform.localRotation;
    32.     }
    33.  
    34.     void Update()
    35.     {
    36.         currentFocusPoint = Vector3.zero;
    37.  
    38.         CalculateCameraFocusPoint();
    39.         CalculateLerp();
    40.     }
    41.  
    42.     #endregion
    43.  
    44.     #region Functions
    45.  
    46.     public void CalculateCameraFocusPoint()
    47.     {
    48.         // If the player is free looking
    49.         if (Input.GetMouseButton(1))
    50.         {
    51.             // Check if there's any camera focus points in range.
    52.             // Start by finding the nearest focus point to the mouse.
    53.             float            nearestDistance = float.MaxValue;
    54.             CameraFocusPoint nearestPoint    = null;
    55.             foreach (CameraFocusPoint focusPoint in focusPoints)
    56.             {
    57.                 Vector3 point    = Camera.main.WorldToScreenPoint(focusPoint.transform.position);
    58.                 float distance   = Vector2.Distance(point, new Vector2(Screen.width / 2, Screen.height / 2));
    59.  
    60.                 if (point.z > 0 && distance < nearestDistance && distance < focusPoint.cameraFocusDistance)
    61.                 {
    62.                     nearestDistance = distance;
    63.                     nearestPoint    = focusPoint;
    64.                 }
    65.             }
    66.  
    67.             if (nearestPoint != null) // FOCUSING //
    68.             {
    69.                 currentFocusPoint = nearestPoint.transform.position;
    70.             }
    71.             else // NORMAL FREE LOOK //
    72.             {
    73.                 rotationX += Input.GetAxis("Mouse X") * sensitivityX;
    74.                 rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
    75.             }
    76.         }
    77.         else // Otherwise keep the camera normal.
    78.         {
    79.             rotationX = 0;
    80.             rotationY = 0;
    81.         }
    82.     }
    83.  
    84.     public void CalculateLerp()
    85.     {
    86.         // If we don't have a focus point
    87.         if (currentFocusPoint == Vector3.zero)
    88.         {
    89.             // Add it to the total.
    90.             rotationArrayX.Add(rotationX);
    91.             rotationArrayY.Add(rotationY);
    92.  
    93.             // Limit the collection.
    94.             if (rotationArrayX.Count >= frameCounter)
    95.             {
    96.                 rotationArrayX.RemoveAt(0);
    97.             }
    98.  
    99.             if (rotationArrayY.Count >= frameCounter)
    100.             {
    101.                 rotationArrayY.RemoveAt(0);
    102.             }
    103.  
    104.             // Calculate the average rotation.
    105.             float rotationAverageX = 0f;
    106.             float rotationAverageY = 0f;
    107.  
    108.             for (int i = 0; i < rotationArrayX.Count; i++)
    109.             {
    110.                 rotationAverageX += rotationArrayX[i];
    111.             }
    112.  
    113.             for (int i = 0; i < rotationArrayY.Count; i++)
    114.             {
    115.                 rotationAverageY += rotationArrayY[i];
    116.             }
    117.  
    118.             rotationAverageX /= rotationArrayX.Count;
    119.             rotationAverageY /= rotationArrayY.Count;
    120.        
    121.             Quaternion xQuaternion = Quaternion.AngleAxis(rotationAverageX, Vector3.up);
    122.             Quaternion yQuaternion = Quaternion.AngleAxis(rotationAverageY, Vector3.left);
    123.  
    124.             transform.localRotation = originalRotation * xQuaternion * yQuaternion;
    125.         }
    126.         else // If we do.
    127.         {
    128.             transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(currentFocusPoint - transform.position), Time.deltaTime * 1);
    129.         }
    130.     }
    131.  
    132.     #endregion
    133. }
    134.  

    Thanks in advance.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    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.
     
  3. thekill473

    thekill473

    Joined:
    Aug 26, 2012
    Posts:
    9
    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.
    Code (CSharp):
    1. rotationX += Input.GetAxis("Mouse X") * sensitivityX;
    2. rotationY += Input.GetAxis("Mouse Y") * sensitivityY;