Search Unity

How to Zoom Into Another Object Using Freelook Camera

Discussion in 'Cinemachine' started by duyanhpham235, Sep 3, 2019.

  1. duyanhpham235

    duyanhpham235

    Joined:
    Jul 21, 2019
    Posts:
    14
    Hi,

    So I'm currently using freelook camera for my character. During the gameplay, there is an event happening. At the beginning of the event, the game will pick randomly a player out of 4 players. What I'm trying to achieve is for other 3 players who don't get chosen, their freelook camera will gradually zooming into the chosen player's character, letting them know where the chosen character is in the level.

    In the video below, I was trying to do that by transiting between 2 cameras but the result is not great. The angle is totally off, not sure how to do this smoothly.



    Hope that makes sense. Thank you
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    2,845
    Sorry, I don't understand the video at all. There is a shot in the middle that you cut to, and then cut away from. That seems unrelated to your text.

    From your text, it seems that you want the other player's camera to look at the chosen character for a moment, and then return to looking at the normal target, all without changing position. is that right?
     
  3. duyanhpham235

    duyanhpham235

    Joined:
    Jul 21, 2019
    Posts:
    14
    Sorry for the confusion.. Yeah what you described is right. I want other players' cameras to start looking at the chosen character at first, and then start zooming in toward that direction. Does that all make sense?
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    2,845
    I think the easiest way to get what you want is to use a CinemachineTargetGroup as a LookAt target. By default, populate the group with a single item: the normal target. For the "look at the other guy" moment, have some code that adds the other guy as a second target to the group with weight 0, and then lerps the weight from 0 to 1, and back to 0 again, while doing the opposite lerp on the main target's weight.
     
  5. duyanhpham235

    duyanhpham235

    Joined:
    Jul 21, 2019
    Posts:
    14
    How can I add another target to the group via code? Are the radiuses set at 0?
     
  6. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    2,845
    By default the radius of each item is 0, but you can set it to whatever you like.

    Just make a List<CinemachineTargetGroup.Target>, modify it, then set group.m_targets = list.ToArray(). Or use group.AddMember() and group.RemoveMember().
     
  7. duyanhpham235

    duyanhpham235

    Joined:
    Jul 21, 2019
    Posts:
    14
    Hey, nothing seems to happen. Here is my set up and code. New targets list get added correctly and the weights lerp fine. But nothing happens.

    For the set up, I simply added the CinemachineTargetGroup script onto the freelook camera and NOT removing the normal "Look At" section. I tried to set normal "Look At" section to none but the camera is just not looking at anything if I do that. Thank you.


    Code (CSharp):
    1.   public IEnumerator ZoomCameraTowardChosenOcotopus(OctoRagdoll myOctopus, OctoRagdoll chosenOcotpus)
    2.     {
    3.         List<CinemachineTargetGroup.Target> targetList = new List<CinemachineTargetGroup.Target>();
    4.  
    5.         var theTargetGroup = myOctopus.ControllingCamera.GetComponent<CinemachineTargetGroup>();
    6.  
    7.         CinemachineTargetGroup.Target myOctopusTarget = new CinemachineTargetGroup.Target();
    8.         myOctopusTarget.target = myOctopus.GetComponent<OctoController>().Flab;
    9.         myOctopusTarget.weight = 1;
    10.         myOctopusTarget.radius = 0;
    11.  
    12.         CinemachineTargetGroup.Target chosenOctopusTarget = new CinemachineTargetGroup.Target();
    13.  
    14.         chosenOctopusTarget.target = chosenOcotpus.transform;
    15.         chosenOctopusTarget.weight = 0;
    16.         chosenOctopusTarget.radius = 0;
    17.  
    18.         targetList.Add(myOctopusTarget);
    19.         targetList.Add(chosenOctopusTarget);
    20.  
    21.         theTargetGroup.m_Targets = targetList.ToArray();
    22.  
    23.         float currentTime = 0;
    24.         while (currentTime < 2f)
    25.         {
    26.             float t = currentTime / 2f;
    27.             theTargetGroup.m_Targets[1].weight = Mathf.Lerp(0, 1, t);
    28.             theTargetGroup.m_Targets[0].weight = Mathf.Lerp(1, 0, t);
    29.             currentTime += Time.deltaTime;
    30.             yield return new WaitForEndOfFrame();
    31.         }
    32.     }
     

    Attached Files:

  8. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    2,845
    The target group needs to be a separate game object. Remove it from the FreeLook, and set the LookAt target to be the group object.
     
  9. duyanhpham235

    duyanhpham235

    Joined:
    Jul 21, 2019
    Posts:
    14
    Its kinda working now after I did what you said. However, its not just the camera zooming in but it also drags the "look at" object and its children along with the zooming in, which is not what I'm looking for.

    Also I can't seem to slow down the zooming in even though I had tried to increase the time with which the value lerps.
     
  10. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    2,845
    I don't understand what you mean.
     
  11. duyanhpham235

    duyanhpham235

    Joined:
    Jul 21, 2019
    Posts:
    14
    So basically when the camera zooms in, the gameObject that has CinemachineTargetGroup goes along with it.

    In the video, you can see that when the camera zooms in, meshes and 3D UI get dragged along with it because they are children of the gameObject that has CinemachineTargetGroup.

    I also attached and image of the set up below.

     

    Attached Files:

  12. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    2,845
    Put the CinemachineTargetGroup on its own empty game object.
     
  13. duyanhpham235

    duyanhpham235

    Joined:
    Jul 21, 2019
    Posts:
    14
    So I put CinemachineTargetGroup on its own empty game object, but for some reasons instead of zooming into the other octopus, it simply looks at it.

    By the way, how can I slow down the zoom if its gonna work?



    Code (CSharp):
    1.         List<CinemachineTargetGroup.Target> targetList = new List<CinemachineTargetGroup.Target>();
    2.  
    3.         var myOctoController = myOctopus.GetComponent<OctoController>();
    4.         myOctopus.ControllingCamera.m_LookAt = myOctoController.GroupObjectsForZooming.transform;
    5.  
    6.         var theTargetGroup = myOctoController.GroupObjectsForZooming.GetComponent<CinemachineTargetGroup>();
    7.  
    8.         CinemachineTargetGroup.Target myOctopusTarget = new CinemachineTargetGroup.Target();
    9.         myOctopusTarget.target = myOctoController.GroupObjectsForZooming.transform;
    10.         myOctopusTarget.weight = 1;
    11.         myOctopusTarget.radius = 0;
    12.  
    13.         CinemachineTargetGroup.Target chosenOctopusTarget = new CinemachineTargetGroup.Target();
    14.  
    15.         chosenOctopusTarget.target = chosenOcotpus.transform;
    16.         chosenOctopusTarget.weight = 0;
    17.         chosenOctopusTarget.radius = 0;
    18.  
    19.         targetList.Add(myOctopusTarget);
    20.         targetList.Add(chosenOctopusTarget);
    21.  
    22.  
    23.         theTargetGroup.m_Targets = targetList.ToArray();
    24.  
    25.         float currentTime = 0;
    26.         while (currentTime < 10f)
    27.         {
    28.             float t = currentTime / 10f;
    29.             theTargetGroup.m_Targets[0].weight = Mathf.Lerp(1, 0, t);
    30.             theTargetGroup.m_Targets[1].weight = Mathf.Lerp(0, 1, t);
    31.             currentTime += Time.deltaTime;
    32.             yield return new WaitForEndOfFrame();
    33.         }
    34.  
    35.         yield return new WaitForSecondsRealtime(2f);
    36.  
    37.         float currentTime2 = 0;
    38.         while (currentTime2 < 10f)
    39.         {
    40.             float t = currentTime2 / 10f;
    41.             theTargetGroup.m_Targets[0].weight = Mathf.Lerp(0, 1, t);
    42.             theTargetGroup.m_Targets[1].weight = Mathf.Lerp(1, 0, t);
    43.             currentTime2 += Time.deltaTime;
    44.             yield return new WaitForEndOfFrame();
    45.         }
    46.  
     
  14. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    2,845
    Sorry, I missed that you also wanted to zoom in. That makes things trickier to do with the target group - maybe we should try a different approach. Get rid of the target group, and try this instead:

    Assuming vcamA is your main vcam that follows the player.
    Make a new vcamB, set it to follow vcamA, with Body = HardLockToTarget. That will match the position of vcamA.
    Set vcamB's Aim to Composer or HardLookAt, with an empty LookAt target for now.
    Add a FollowZoom extension, and set the Width parameter to be a little larger than an octopus - adjust for the framing you want. This will zoom into the LookAt target once it is set.
    Normally, vcamB is deactivated.

    When the LookAtOtherPlayer moment begins, set vacmB's LookAt to the other player. Then activate vcamB, wait 2 seconds, and deactivate it. The brain will take care of the blending - you can give it a custom blend setting for vcamB to make that blend time and style be whatever you like.