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

Smooth Camera Movement

Discussion in 'Scripting' started by Browdaddy96, May 28, 2016.

  1. Browdaddy96

    Browdaddy96

    Joined:
    Aug 27, 2015
    Posts:
    82
    Sorry for the Jaden Smith title, I am making a game were the camera isn't attached to the player, and the player makes clicking decisions(The Crucible, act 4) to determine what certain models do/say. That works fine, my issue comes from me wanting every time I click I want the camera to smoothly transition from where it is to a pre determined way point. The problem is it instantly translates to the spot.
    Code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class CameraWaypoints : MonoBehaviour {
    6.     public List<Vector3> posiblepositions;
    7.  
    8.     public Transform targetPosForRotation;
    9.  
    10.     public Camera mainCam;
    11.  
    12.     void Update () {
    13.         if (Input.GetMouseButtonDown(0)) {
    14.  
    15.             MoveCamera();
    16.         }  
    17.     }
    18.  
    19.     void MoveCamera()
    20.     {
    21.         int randomSpot = Random.Range(0, posiblepositions.Count);
    22.  
    23.         mainCam.transform.position = Vector3.Lerp(mainCam.transform.position, posiblepositions[randomSpot], 3f);
    24.         mainCam.transform.LookAt(targetPosForRotation);
    25.     }
    26. }
    27.  
     
  2. Craig8726

    Craig8726

    Joined:
    Jul 5, 2013
    Posts:
    79
    Its probably because the moveCamera method is only being called on one frame. It is in update which is called every frame but it is restricted with Input.GetMouseButtonDown witch only registers when the mouse is clicked down. The lerp needs multiple frames to interpolate a path over some time.

    Try using a bool that is true when you click to use the method in update.
     
  3. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    I'd suggest using a tweening framework such as DOTween:
    http://dotween.demigiant.com

    Also, instead of using Vector3 for your camera possible positions, use transforms instead, this way you can manually place the pre-defined position using emptys, so you can grab them around in the scene view instead of typing the values in the inspector.

    You code would be then:
    Code (CSharp):
    1. using UnityEngine;
    2. using DG.Tweening;
    3.  
    4. public class CameraWaypoints : MonoBehaviour
    5. {
    6.     public float transitionDuration = 1.0f;
    7.     public Transform[] posiblepositions;
    8.  
    9.     public Transform targetPosForRotation;
    10.  
    11.     public Camera mainCam;
    12.  
    13.     void Update()
    14.     {
    15.         if (Input.GetMouseButtonDown(0))
    16.         {
    17.             MoveCamera();
    18.         }
    19.     }
    20.  
    21.     void MoveCamera()
    22.     {
    23.         int randomSpot = Random.Range(0, posiblepositions.Length);
    24.  
    25.         mainCam.transform.DOMove(posiblepositions[randomSpot].position, transitionDuration);
    26.         mainCam.transform.DOLookAt(targetPosForRotation.position, transitionDuration);
    27.     }
    28. }
     
    Last edited: May 28, 2016
  4. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,960
    The third parameter in Lerp, t, is a value clamped to [0, 1] that determines how close the result is to the target. The first problem is that you're fixing it at 3 which would clamp it to 1. This means your object gets to its target immediately. The second problem is that you are are not animating the time.
    Code (CSharp):
    1. transform.position = Vector3.Lerp (mainCam.transform.position, possiblepositions[randomSpot], elapsedTime);
    2. elapsedTime += Time.deltaTime;
     
  5. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,960
    I'm not sure that much overhead (DOTween API) is necessary for such an easy move. But it would be a considerable improvement if using it for a lot of objects.
     
  6. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Where the overhead would be?
    How would it be simpler than that?
     
  7. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,960
    I don't mean a performance overhead at all. It is good software design to keep the codebase as lean as possible. This means using external API's if and only if they are necessary. In this case, it doesn't seem to be at all. Your code with DOTween and his with Vector3 look identical; so there isn't as big a need to use an external API.
     
  8. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Oops, there is a problem with the camera rotation: The camera is looking at the target from the start position, not from the destination position. Here is a fix:

    Code (CSharp):
    1.     void MoveCamera()
    2.     {
    3.         int randomSpot = Random.Range(0, posiblepositions.Length);
    4.  
    5.         var destination = posiblepositions[randomSpot].position;
    6.         var viewDirection = (targetPosForRotation.position - destination).normalized;
    7.         var lookAtRotation = Quaternion.LookRotation(viewDirection);
    8.  
    9.         mainCam.transform.DOMove(destination, transitionDuration);
    10.         mainCam.transform.DORotateQuaternion(lookAtRotation, transitionDuration);
    11.     }
    Me neither.
    Agree.
    Well, using external tools could help making the code neater.

    It looks almost identical, excepted that now it does the expected job.
     
    andreiagmu likes this.