Search Unity

Cinemachine -Target Follow an Initialize Prefab

Discussion in 'Cinemachine' started by nlv22, Sep 23, 2018.

  1. nlv22

    nlv22

    Joined:
    Dec 20, 2016
    Posts:
    31
    Since my player gets initialized in runtime, I am trying to add cinemachine's target and follow through code. What I tried below is not working:

    Inside the Cinemachine Virtual Camera Script I change

    override public Transform LookAt
    {
    get { return ResolveLookAt(m_LookAt); }
    set { m_LookAt = value; }
    }

    override public Transform Follow
    {

    get { return ResolveFollow(m_Follow); }
    set { m_Follow = value; }
    }

    To this:

    override public Transform LookAt
    {
    get { return ResolveLookAt(m_LookAt); }
    set { m_LookAt = GameObject.Find("Player").transform; }
    }

    override public Transform Follow
    {

    get { return ResolveFollow(m_Follow); }
    set { m_Follow = GameObject.Find("Player").transform; }
    }


     
    murp35 likes this.
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    @novavillanueva22 Don't do that. Leave CinemachineVirtualCamera.cs alone. Instead, have another script that does:
    Code (CSharp):
    1. var vcam = GetComponent<CinemachineVirtualCamera>();
    2. vcam.LookAt = bla;
    3. vcam.Follow = bla;
     
    Jroel, Gerzent, YankeeTurtle and 15 others like this.
  3. nlv22

    nlv22

    Joined:
    Dec 20, 2016
    Posts:
    31
    Thanks! I made another script (see below). It finds the initialize player as a target in the new FollowPlayer Script but doesn't do anything to Cinemachine. Seems I am missing something.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Cinemachine;
    5.  
    6. public class FollowPlayer : MonoBehaviour
    7. {
    8.  
    9.  
    10.     public GameObject tPlayer;
    11.     public Transform tFollowTarget;
    12.     private CinemachineVirtualCamera vcam;
    13.  
    14.     void Start()
    15.     {
    16.         var vcam = GetComponent<CinemachineVirtualCamera>();
    17.     }
    18.  
    19.     void Update()
    20.     {
    21.         if (tPlayer == null)
    22.         {
    23.             tPlayer = GameObject.FindWithTag("Player");
    24.         }
    25.         tFollowTarget = tPlayer.transform;
    26.         vcam.LookAt = tFollowTarget;
    27.         vcam.Follow = tFollowTarget;
    28.     }
    29. }
    30.  
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    To which game object did you attach this script?
    Also: all the code should be in Start(), no need to do it every frame in Update().
     
    Rafaelligeiro likes this.
  5. nlv22

    nlv22

    Joined:
    Dec 20, 2016
    Posts:
    31
    I've attached the script to the CM vcam1 camera GameObject Cinemachine makes when you add a camera. I do not have any other cameras in the scene. If I manually add the player prefab at runtime, Cinemachine (follow target) does work.

    It highlights 'vcam.LookAt = tFollowTarget;' as an error (which I'm guessing the previous line may be the problem) that reads:

    NullReferenceException: Object reference not set to an instance of an object
    FollowPlayer.Update () (at Assets/FollowPlayer.cs:26)
     

    Attached Files:

  6. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    Probably tPlayer is null. Unity won't find it if it's not in the scene.
    Also, the virtual camera should not have a Camera component. Best to remove it.
     
  7. nlv22

    nlv22

    Joined:
    Dec 20, 2016
    Posts:
    31
    tPlayer is found after the game starts as show on this new screenshot attached. I am sorry, I didn't have this showing before. The Player does not start in the scene- it gets initialized after. This is a multi player setup. Is this some overriding Cinemachine problem?

    Oh, this camera component was created by Cinemachine's when I added a 'Create 2d Camera'. My virtual camera doesn't seem to work without it.
     

    Attached Files:

  8. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    In that case, leave your code in Update(), but you must handle the case where tPlayer is null because it hasn't been spawned yet:
    Code (CSharp):
    1.     void Update()
    2.     {
    3.         if (tPlayer == null)
    4.         {
    5.             tPlayer = GameObject.FindWithTag("Player");
    6.             if (tPlayer != null)
    7.             {
    8.                 tFollowTarget = tPlayer.transform;
    9.                 vcam.LookAt = tFollowTarget;
    10.                 vcam.Follow = tFollowTarget;
    11.             }
    12.         }
    13.     }
    Cinemachine will never create a Camera component for you. It should not be there.
    Can you show me your inspector for the Main Camera? The one with the Brain.
     
    Vainusy likes this.
  9. nlv22

    nlv22

    Joined:
    Dec 20, 2016
    Posts:
    31
    Thanks for all the help so far. I really appreciated. I updated the code as illustrated above which made things better by the console not throwing 100s of lines.

    The connection to Cinemachine seems to still be missing. You were right that the camera with the brain doesn't have another camera. Only the vCM vcam1 GameObject has another camera. I've attached a screenshot for each.

    The same error appears: NullReferenceException: Object reference not set to an instance of an object
    FollowPlayer.Update () (at Assets/FollowPlayer.cs:33)



    Capture.JPG Capture2.JPG

    .
     
  10. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    The problem is that the structure is wrong. Somehow it got mixed up. You should have this:

    GameObject1: Tag: MainCamera
    - Camera
    - Audio Listener
    - CinemachineBrain

    GameObject2: CM vcam1
    - VirtualCamera
    - FollowPlayer

    The job of the brain is to monitor all the active vcams in the scene, and position itself (and the Camera) according to the one with the highest priority, and do blends when a different vcam is activated.

    If you start with an empty scene and do Cinemachine/CreateVirtualCamera, you will see that you get this structure.
     
    murp35 likes this.
  11. nlv22

    nlv22

    Joined:
    Dec 20, 2016
    Posts:
    31
    Works now!

    When I made a new fresh scene as you advised, I realized that the warnings were turn off in the other project that read 'vcam was assigned but not used' so that the error of 'Object reference not set to an instance of an object' was not the only thing. Sorry about that, that would have been useful knowledge for troubleshooting.

    In the code I accidentally wrote:

    [B]var vcam = GetComponent<CinemachineVirtualCamera>(); [/B]


    instead of just:

    [B]vcam = GetComponent<CinemachineVirtualCamera>();[/B] 


    From the new clean project I did see that my setup is a bit strange with an additional camera. Although its working, I'll correct that just in case of future problems. So the final code is now:

    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. public class FollowPlayer : MonoBehaviour
    5. {
    6.     public GameObject tPlayer;
    7.     public Transform tFollowTarget;
    8.     private CinemachineVirtualCamera vcam;
    9.  
    10.     // Use this for initialization
    11.     void Start()
    12.     {
    13.         vcam = GetComponent<CinemachineVirtualCamera>();
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void Update()
    18.     {
    19.         if (tPlayer == null)
    20.         {
    21.             tPlayer = GameObject.FindWithTag("Player");
    22.             if (tPlayer != null)
    23.             {
    24.                 tFollowTarget = tPlayer.transform;
    25.                 vcam.LookAt = tFollowTarget;
    26.                 vcam.Follow = tFollowTarget;
    27.             }
    28.         }
    29.     }
    30. }
    Much thanks to you Greg!
     
    Majistic, ToyBrain101 and CaliSangren like this.
  12. duanegra

    duanegra

    Joined:
    Aug 28, 2018
    Posts:
    10
    There is another way to handle this problem. Combine the object that you want to follow (such as Player), and the virtual camera in one prefab. This can be done by making them children of an empty game object. Be sure set the Follow, and Look at targets before making the prefab. Also be sure the set the positions of the components to zero. Now you can Instantiate them all at once, and the v-cam will follow the object.

    I hope this helps. All the best!
     
  13. blastedw

    blastedw

    Joined:
    Apr 29, 2019
    Posts:
    13
  14. ZZRTheBeasT

    ZZRTheBeasT

    Joined:
    Jan 16, 2020
    Posts:
    1
    I cannot use var
     
  15. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    CinemachineVirtualCamera vcam = GetComponent<CinemachineVirtualCamera>();
     
    DreamSpaceYL and a01024592 like this.
  16. ShonySion

    ShonySion

    Joined:
    Jul 9, 2020
    Posts:
    1
    my
    public CinemachineVirtualCamera vcam;
    line Gets An error CS0246 pls help
     
  17. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    @ShonySion Do you have
    using Cinemachine;
    at the top?
     
  18. MathewHI

    MathewHI

    Joined:
    Mar 29, 2016
    Posts:
    501
    Good idea but you will have to also write code to instantiate a new version of cinemachine. I tried your idea it works except for the fact that when I instantiate my player it destroys previous players and adds an new one, this separates the prefab the cinemachine and player into two in the heirarchy.
     
  19. radiantboy

    radiantboy

    Joined:
    Nov 21, 2012
    Posts:
    1,633
    So no matter what I try I cannot assign follow or lookat from code. It works fine if I drag them into inspector, is there something special I need to do to assign from code??
     
  20. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    It should just work.
    Can you show the code?
     
    radiantboy likes this.
  21. radiantboy

    radiantboy

    Joined:
    Nov 21, 2012
    Posts:
    1,633
    Sorry it was my own logic error, works now. Making cutscenes in cinemachine :)
     
  22. stickylab

    stickylab

    Joined:
    Mar 16, 2016
    Posts:
    92

    thanks i can
     
  23. unity_j5kBcnB2bjs9kg

    unity_j5kBcnB2bjs9kg

    Joined:
    Jan 20, 2022
    Posts:
    1

    Brooooo. You just saved my life. I love you.
     
    harlandpj likes this.
  24. LouWorldOrder

    LouWorldOrder

    Joined:
    Oct 24, 2022
    Posts:
    14
    Alright, I have a question.

    I am trying to get this to work, I think I have got the script exactly as it is in this thread. But it won't work for me. If I play and pause, I can drag the instantiated clone into Follow/LookAt of the CM Vcam and when I unpause it will give me the behavior I am looking for. But not when I just hit play.

    Don't know if this makes a difference but I am doing this in 2D. Using a 2D vcam (although I have tried Virtual Camera too, to no avail). Either I am doing something wrong in Unity itself or some of the scripting has changed? I do have using Cinemachine in there at the top as well.

    Code (CSharp):
    1. private CinemachineVirtualCamera vcam;
    2.  
    3.     // Start is called before the first frame update
    4.     void Start()
    5.     {
    6.        //CinemachineVirtualCamera
    7.        vcam = GetComponent<CinemachineVirtualCamera>();
    8.     }
    9.  
    10.     // Update is called once per frame
    11.     void Update()
    12.     {
    13.        if (tPlayer == null)
    14.        {
    15.         tPlayer = GameObject.FindWithTag("Player");
    16.         if(tPlayer != null)
    17.         {
    18.             tFollowTarget = tPlayer.transform;
    19.             vcam.LookAt = tFollowTarget;
    20.             vcam.Follow = tFollowTarget;
    21.         }
    22.        }
    23.     }
    24. }
    25.  
    And I do have my prefab tagged as "Player".

    The Instantiate code is as follows:
    Code (CSharp):
    1. public GameObject projectile;
    2.     public float launchVelocity = 700.0f;
    3.      
    4.     // Start is called before the first frame update
    5.     void Start()
    6.     {
    7.      
    8.     }
    9.  
    10.     // Update is called once per frame
    11.     void Update()
    12.     {
    13.       if (Input.GetButtonDown("Fire1"))
    14.       {
    15.         GameObject ball = Instantiate(projectile, transform.position, transform.rotation);
    16.         ball.GetComponent<Rigidbody2D>().AddRelativeForce(new Vector3(0, launchVelocity, 0));
    17.       }
    18.     }
    UPDATE: Changed the code above to what worked for me! I just had to change the GetComponent code, to only reference vcam and leave out CinemachineVirtualCam (although you need that when creating the variable).

    It wasn't throwing me an error so I had no idea. Oh, I also changed all Follow and LookAts (on both the vcam and the script) to None, to start. Pretty sure it was the code change that did it though.
     
    Last edited: Nov 10, 2022
  25. LouWorldOrder

    LouWorldOrder

    Joined:
    Oct 24, 2022
    Posts:
    14
    No one has any ideas?
     
  26. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    Maybe you can give some context. The code you show for instantiation has apparently nothing to do with the problem you are describing, so I am just confused. Try showing some inspectors so we know what's attached to what.
     
  27. LouWorldOrder

    LouWorldOrder

    Joined:
    Oct 24, 2022
    Posts:
    14

    Sphere is the name of the prefab I am instantiating and trying to get the camera to track/follow. When I play the scene, pause it, and drag the instantiated object into Follow/Look At, it works when I unpause. But it doesn't work if I drag the instantiated object into T Player or T Follow Target. Nor does it work just by playing the scene.

    Edit: And this script is attached to the vcam.

    I will upload the inspector for the Main Camera as well.
     
  28. LouWorldOrder

    LouWorldOrder

    Joined:
    Oct 24, 2022
    Posts:
    14

    Main Camera inspector
     
  29. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    Please show the inspector for the instantiated sphere
     
  30. LouWorldOrder

    LouWorldOrder

    Joined:
    Oct 24, 2022
    Posts:
    14

    The 'Player' tag is just the default Player tag, I did not create a new one named 'Player'.
     
  31. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    When you instantiate it, does the prefab instance also get the tag?
     
  32. LouWorldOrder

    LouWorldOrder

    Joined:
    Oct 24, 2022
    Posts:
    14
    Yes, my Sphere (Clone) also has the player tag.
     
  33. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    Try putting a breakpoint in the Update() method of your script. Step through the code. Does it not find the gameObject? What happens?
     
  34. LouWorldOrder

    LouWorldOrder

    Joined:
    Oct 24, 2022
    Posts:
    14
    Sorry I'm still quite new (started with tutorials about 3 weeks ago). How do I do that?
     
  35. LouWorldOrder

    LouWorldOrder

    Joined:
    Oct 24, 2022
    Posts:
    14
    This is driving me nuts. Are there some other ways to get the camera to track a player/object with force applied? Is there a way to apply force to the camera, iow apply the same force to the camera as to the object?

    Should I maybe just settle for hardcoding the transform on the camera, for better or for worse?
     
  36. LouWorldOrder

    LouWorldOrder

    Joined:
    Oct 24, 2022
    Posts:
    14
    OK... So...

    //CinemachineVirtualCamera
    vcam = GetComponent<CinemachineVirtualCamera>();

    That was the moneymaker! I almost couldn't believe my eyes when the camera started actually tracking the projectile!
     
    Gregoryl likes this.
  37. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    Glad you found the solution. Nice to get up in the morning and see this.
     
    LouWorldOrder likes this.
  38. LouWorldOrder

    LouWorldOrder

    Joined:
    Oct 24, 2022
    Posts:
    14
    I knew I was close, man. It's one of those things where you are afraid of breaking things further, and then you'll never find the 'one' thing that's wrong. So it was a case of taking a calculated risk, one at a time, learning to problem solve some code, use comments to change code the minimum amount possible at a time! And then I just had to think why was the Virtual Camera not receiving instructions/following orders!

    Thanks for your help, because without your code (from years back) and your eyeballs on this, to assure me there wasn't anything wrong with the vast majority of what I was doing, I wouldn't have had the confidence or the required stubborn persistence to finally track down the issue!
     
    Gregoryl likes this.
  39. alizulfiqar22222

    alizulfiqar22222

    Joined:
    Sep 9, 2023
    Posts:
    1
    I have a problem. Everything is fine, my virtual cam gets assigned what to look at and follow. But my camera is somewhere above where it should be and stuck there. Its not following my car...
     
  40. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,724
    Can you show the vcam inspector?