Search Unity

Create multiple VCs, store in List, access from external script

Discussion in 'Cinemachine' started by TimHellmann, Jul 22, 2017.

  1. TimHellmann

    TimHellmann

    Joined:
    Mar 6, 2011
    Posts:
    66
    Hello dear wonderful Cinemachine devs.
    So I try to create multiple virtual cameras, one for each player character in a scene, then want to store them as a List and switch / activate / configure them by an external script.

    That does not seem to work for me atm. as multiple solutions just do not work here.
    At that, for me, the example scripts / example scenes are not explaining the C# alternative. I am sure you will improve and update that in the future. :)

    What do I want to achieve in detail?
    1. Create multiple VCs via code, one for each player character to use of the great blending between VCs. (works)
    2. Store them into a List, either of type GameObject or CinemachineVirtualCamera, depending on what works in the end. (does not work)
    3. Access the Cinemachine camera script from an external game manager to activate / deactivate the specific camera linked to the player character (does not work)
    4. Work with the previously created List / the objects in it via accessing, say, VC [5] in the List. (does not work)

    My problems:
    The example scene in which you show how to switch between multiple (state-driven) cameras is great to see the effect but it does not show the C# code alternative afaik.
    I cannot seem to access the GameObject of the VC to use SetActive(true/false) or other functions.
    It both seems not to be allowed to first create the GameObject, store it and then add the virtual camera component and I am not allowed to access the GameObject of the VC.

    I seem to have missed some helpful information for this purpose or I just think the wrong way.

    My camera code (excerpt):
    Code (CSharp):
    1. public CinemachineVirtualCamera vcam;
    2. public List<CinemachineVirtualCamera> vcameras;
    3.  
    4. void Start(){
    5. vcameras = new List<CinemachineVirtualCamera> ();
    6.   foreach (GameObject player in GetComponent<Players>().existingPlayers) {
    7.    
    8.    // Create a virtual camera that looks at object "Cube", and set some settings
    9.    vcam = new GameObject ("Virtual Camera").AddComponent<CinemachineVirtualCamera> ();
    10.  
    11.    vcameras.Add (vcam);
    12.    }
    13. }
    14.  
    Manager:
    Code (CSharp):
    1. void Start(){
    2.    foreach (CinemachineVirtualCamera vcamera in GetComponent<CameraManager>().vcameras) {
    3.       vcamera.gameObject.SetActive (false);
    4.    }
    5.    GetComponent<CameraManager> ().vcameras[0].gameObject.SetActive (true);
    6. }
    7.  
    8. void Update(){
    9.  
    10. // If player hits a button, switch to next player / VC, for example via:
    11. vcameras[2].gameObject.SetActive(true);
    12. // or a similar, working code
    13. }
    14.  
    (Both scripts are components of the GameManager)

    When I try the code this way, I cannot access the gameObject via vcameras[0].gameObject by the external manager.
    Error says List is null / array out of range but it is filled with the right amount of cameras in the Inspector.
    This error also occurs if I want to access the virtual camera component.

    My failed workaround:
    First create the vcam as a GameObject, store it in a List<GameObject>, then add the CinemachineVirtualCamera component to it. The error tells me type conflicts between GameObject and CinemachineVirtualCamera.

    Can somebody of the rad people here help me further?
    I'd appreciate it a lot. Thank you so much.
     
    Last edited: Jul 22, 2017
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    @AriesT It looks to me as though you have a script ordering problem. Unity does not guarantee the calling order of the Start() method. If the second one in your example is called before the first one, then you will get the sort of errors you describe.

    As for creating the cameras themselves from code, you can find examples in the Editor/CinemachineMenu.cs file. That might prove helpful.
     
  3. TimHellmann

    TimHellmann

    Joined:
    Mar 6, 2011
    Posts:
    66
    @Gregoryl Thank you for the quick reply. I knew it must be something as obvious as that. Alright, my bad. The problem has nothing to do with Cinemachine. :rolleyes:

    Putting some relevant code pieces into Awake instead of the Start solved many issues.
    One concluding question though. Is there a solution that guarantees a desired Start order besides having chunks in the Awake method?

    This thread can be closed as solved if desired.
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Yes you can control the script order. See https://docs.unity3d.com/Manual/class-ScriptExecution.html.
    However, you might consider refactoring you code so that it no longer depends on script order. Most of the time this is a better solution, as it tends to lead toward more robust code.