Search Unity

Bug Confiner and boundaries change on scene change

Discussion in 'Cinemachine' started by asafrokni, Oct 22, 2022.

  1. asafrokni

    asafrokni

    Joined:
    Aug 20, 2021
    Posts:
    4
    Hi guys,
    Fairly new with the Cinemachine and could really use some help.
    I'm building a 2D game where each scene is a new level, and I'm using Cinemachine to follow the player around.
    I'm using a confiner I made (PolygonCollider2D) and it works fine basically, but if I swap to a new scene it's all messed up since the confiner is not dynamically changing obviously.

    So I wrote a script and in the script I'm looking for an object with the tag "Confiner" (only one exists in each scene) and placing it into the Cinemachine, but it's not working.. Now I'm getting an error:

    NullReferenceException: Object reference not set to an instance of an object
    CameraMovement.Awake()... At line 30.

    this is line 30:
    Code (CSharp):
    1. confiner.InvalidatePathCache();
    And the whole code:
    Code (CSharp):
    1. private void Awake()
    2.     {
    3.         cameraPosition = this.transform.position;
    4.         cinemachineBrain = this.GetComponent<CinemachineBrain>();
    5.         confiner = cinemachineBrain.GetComponent<CinemachineConfiner>();
    6.         confiner.InvalidatePathCache();
    7.         confiner.m_BoundingShape2D = GameObject.FindGameObjectWithTag("Confiner").GetComponent<PolygonCollider2D>();
    8.     }
    When I check if the gameobject even exists (simple if statement) it was fine, the object is found, but the changing of the parameter is not working.

    If I remove the line with Invalidate the error simple moves to the next line.

    And last thing:
    In the Update() method of the script I've written code to allow the player to press Alt+WASD and move the camera a bit away from the player to look around. Once I added the code above (the confiner part) it messed it all up and it's like disabling the code, which is weird to me since these are the first lines:
    Code (CSharp):
    1. void Update()
    2.     {
    3.         if (Input.GetKey(KeyCode.F))
    4.         {
    5.             cinemachineBrain.enabled = false;
    6.             playerMovement.enabled = false;
    7.             if (Input.GetKey(KeyCode.W))
    8.             {
    Which is to say that I'm not even using the Cinemachine anymore once the player pressed "F"!

    Any help would be appreciated!! Thank you :)
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    You are looking for the confiner on the CinemachineBrain, which suggests that your setup is incorrect. Can you please show an image of your hierarchy, including the main camera, the vcam, and the confiner bounds object.
     
  3. asafrokni

    asafrokni

    Joined:
    Aug 20, 2021
    Posts:
    4
    I'm looking for the confiner globally in the hierarchy and it's the only object with that Tag (Confiner) in order to avoid mistakes.
    The reason is because I want the code to dynamically swap confiners (and borders of the level) when I'm swapping levels.
    If this helps, I've also attached the inspector's view of the CM vcam1 object.
     

    Attached Files:

  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Thanks for the images.

    So yes, your setup is wrong. Your vcam should not be a child of the main camera. Keep them as separate objects, not parented to each other. The brain's job is to find the active vcam in the current scene, and to drive the camera using the vcam as input. A parent/child relationship is not only superfluous, but it can also create feedback problems.

    Once you have separated the objects, you will find that each scene can have its own vcam with its own confiner, already set up. When the scene is loaded, the brain will find the vcam automatically and use it.

    The only thing you need to do when the scene is loaded is to find the vcam and set the player as its target.
     
  5. asafrokni

    asafrokni

    Joined:
    Aug 20, 2021
    Posts:
    4
    Ok I see what you mean, I was referring to the MainCamera's CinemachineBrain rather than the CM vcam1's confiner basically.

    I'd still rather use a dynamic code to throw unto the MainCamera and refer to the child actually to fill the confiner since it will make the whole hierarchy cleaner and easier to navigate for me, so do you think that FindInChildren might do the trick or is there an actual problem with having the CM vcam as a child of the camera?

    Also, since I want to keep the camera (and the CM and the Player) to the next level I'm planning to use DontDestroyOnLoad(), will that mean I need to do the InvalidatePathCache() method before reassigning the new level's confiner? If so, how should I approach it?
     
  6. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,711
    Making the vcam a child of the main camera is not a good idea. It can create feedback problems. Maybe you are not seeing them with your current setup, but this is a bug waiting to happen. It's not difficult to make them siblings. You should do that.

    To find the CinemachineConfiner, just do confiner = vcam.GetComponent<CinemachineCodfiner>(). Then you can set settings and call methods inside the confiner.
     
  7. asafrokni

    asafrokni

    Joined:
    Aug 20, 2021
    Posts:
    4
    What do you mean by siblings? And what sort of bugs might occur due to having it a child of the main camera?
    As you say, in the current setup I can't see any error but I'm probably missing something that might hurt in the future...

    And by the way, so far it works as you suggested so thank you very very much!!! :)