Search Unity

State Driven Camera (SDC) apparent regression in 2.4.0

Discussion in 'Cinemachine' started by Whatever560, Jan 24, 2020.

  1. Whatever560

    Whatever560

    Joined:
    Jan 5, 2016
    Posts:
    517
    Hi,
    I'm heavily relying on StateDrivenCamera, however in a scene setup that was working perfectly well previous camera don't get deactivated when changing the state. I tried debugging internally (ChooseCurrentCamera and InternalUpdateCameraState) and I don't see how the code deactivate previous camera

    CM_MainLoop should be deactivated here. Going back and force state calls InternalUpdateCameraState but don't disable either of the two

    upload_2020-1-24_12-1-20.png

    upload_2020-1-24_12-0-23.png

    upload_2020-1-24_12-0-56.png

    [Edit 1]:
    I steped in :
    public override void OnTransitionFromCamera(
    ICinemachineCamera fromCam, Vector3 worldUp, float deltaTime)

    fromCam is CM_MainLoop as expected, "this." is CM_CollectionCamera. However no deactivation here. I also tried putting steps on `AddActiveCamera` and `RemoveActiveCamera` it never steps in
     
    Last edited: Jan 24, 2020
  2. Whatever560

    Whatever560

    Joined:
    Jan 5, 2016
    Posts:
    517
    So I'm looking at previous State Driven Camera code before the rewrite :

    You were iterating through all cams and deactivating those not being the "best" (Not sur it was a good practice, letting the transition do the deactivation feels indeed better)
    Code (CSharp):
    1.   if (m_ChildCameras != null)
    2.             {
    3.                 for (int i = 0; i < m_ChildCameras.Length; ++i)
    4.                 {
    5.                     CinemachineVirtualCameraBase vcam  = m_ChildCameras[i];
    6.                     if (vcam != null)
    7.                     {
    8.                         bool enableChild = m_EnableAllChildCameras || vcam == best;
    9.                         if (enableChild != vcam.VirtualCameraGameObject.activeInHierarchy)
    10.                         {
    11.                             vcam.gameObject.SetActive(enableChild);
    12.                             if (enableChild)
    13.                                 CinemachineCore.Instance.UpdateVirtualCamera(vcam, worldUp, deltaTime);
    14.                         }
    15.                     }
    16.                 }
    17.             }
    I implemented this myself previously and it was VERY useful, I think I can manage it with an extension however so it can be extended to any type of VCam.
    Code (CSharp):
    1.  if (mActiveBlend != null)
    2.             {
    3.                 mActiveBlend.UpdateCameraState(worldUp, deltaTime);
    4.                 m_State = mActiveBlend.State;
    5.             }
    6.             else if (LiveChild != null)
    7.             {
    8.                 if (m_InheritChildPriority)
    9.                 {
    10.                     Priority = LiveChild.Priority;
    11.                 }
    12.                 m_State = LiveChild.State;
    13.             }
     

    Attached Files:

  3. Whatever560

    Whatever560

    Joined:
    Jan 5, 2016
    Posts:
    517
    It's pretty rough but here is an extension that handles child priority inheritance, I'm pretty sure it could be included in the package if you feel so. Also there is a small fix for state driven camera not deactivating children.

    It seems to work on my project (there is a couple of extension method, use builtin "as" keywork and ! operator for the bool)

    Code (CSharp):
    1.  
    2.  
    3.     public class CinemachineInheritChildPriority : CinemachineExtension, IHasUpdate
    4.     {
    5.         [Tooltip("If recursive retrieve all childs in hierarchy otherwise only direct childs")]
    6.         public bool Recursive = false;
    7.  
    8.         [Tooltip("Set childs list to be updated at each frame instead of awake")]
    9.         public bool AlwayUpdateChildList = false;
    10.         private List<CinemachineVirtualCameraBase> _childs;
    11.         private CinemachineVirtualCameraBase _cinemachineCameraRoot;
    12.  
    13.         protected override void Awake()
    14.         {
    15.             base.Awake();
    16.             UpdateChildren();
    17.             _cinemachineCameraRoot = GetComponent<CinemachineVirtualCameraBase>();
    18.         }
    19.         private void UpdateChildren()
    20.         {
    21.             var childs = GetComponentsInChildren<CinemachineVirtualCameraBase>(includeInactive: true)
    22.                 //Do not take root object as child
    23.                 .Where(c => c.gameObject != gameObject);
    24.             _childs = (Recursive ? childs.Where(c => c.gameObject.transform.parent.gameObject == gameObject) : childs).ToList();
    25.         }
    26.  
    27.         protected override void PostPipelineStageCallback(CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    28.         {
    29.             var isNotRootCamera = ReferenceEquals(vcam.gameObject, gameObject).IsFalse();
    30.  
    31.             //BUG Dirty state driven camera fix
    32.             if (isNotRootCamera)
    33.             {
    34.                 _cinemachineCameraRoot
    35.                     .AsOptional<CinemachineStateDrivenCamera>()
    36.                     .IfPresent(sdc =>
    37.                     {
    38.                         if (ReferenceEquals(vcam, sdc.LiveChild)) return;
    39.                         vcam.gameObject.SetActive(false);
    40.                     });
    41.             }
    42.  
    43.             //only apply on root camera
    44.             if ( isNotRootCamera ) return;
    45.        
    46.             var priority = _childs.Where(c => c.isActiveAndEnabled)
    47.                 .OrderByDescending(c => c.Priority).Select(c => c.Priority)
    48.                 .FallbackIfEmpty(int.MinValue)
    49.                 .First();
    50.             if(priority == int.MinValue)return;
    51.             vcam.Priority = priority;
    52.         }
    53.  
    54.         public void Update()
    55.         {
    56.             if(AlwayUpdateChildList) UpdateChildren();
    57.         }
    58.     }
    59.