[Bug]: Cinemachine Integration: Cinemachine .UpdateFreeLookCameraValues uses wrong camera in a multi vcam setup

echtnice

Member
1. Character controller variant (Ultimate Character Controller, First Person Controller, etc).
Third Person Controller 2.2
Cinemachine Integration
Cinemachine 2.5.0

2. Unity version (include which SRP, beta Unity versions aren't supported)
2019.3.9f1

3. Bug description
- I have 2 ViewTypes, each with it's own FreeLookVCam
- I use the "State system" to switch between the two ViewTypes
- I use the OnChangeViewType Event of the camera controller to switch the Vcam using the following code:
Code:
    private void OnChangeViewType(ViewType viewType, bool isActive)
    {
        var vcams = m_CameraController.Character.GetComponentsInChildren<CinemachineVirtualCameraBase>();
        foreach (var vcam in vcams)
        {
            var viewTypeName = (viewType.FirstPersonPerspective ? "FirstPerson" : "ThirdPerson") + viewType.GetType().Name;
            vcam.Priority = vcam.gameObject.name == viewTypeName ? 11 : 10;
        }
    }

- When CameraController:SetViewType() kicks in, it calls m_ViewType.ChangeViewType() before executing the "OnChangeViewType" event
- As a result, Cinemachine.UpdateFreeLookCameraValues:186 m_Brain.ActiveVirtualCamera, still references the old VCam.
- Actually, executing a new "OnWillChangeViewType" event before the m_ViewType.ChangeViewType() call in CameraController:SetViewType() does not work either (because the VCam Brain will only update the ActiveVirtualCamera in the next Frame?)

- Changing Cinemachine:ChangeViewType() to always subscribe to the m_CameraActicatedEvent solves the problem for me. This updates the FreeLookCameraValues twice but that should be fine IMHO:

Code:
        public override void ChangeViewType(bool activate, float pitch, float yaw, Quaternion characterRotation)
        {
            m_Brain.enabled = activate;
            if (activate) {
                m_Pitch = pitch;
                if (m_Camera.fieldOfView != m_FieldOfView) {
                    m_FieldOfViewChangeTime = Time.time + m_FieldOfViewDamping / m_CharacterLocomotion.TimeScale;
                }

                // A virtual camera will not exist when Cinemachine first starts.
                if (m_Brain.ActiveVirtualCamera == null) {
                    m_Brain.m_CameraActivatedEvent.AddListener(ActivatedVirtualCamera);
                } else {
+                  m_Brain.m_CameraActivatedEvent.AddListener(ActivatedVirtualCamera);
                    UpdateFreeLookCameraValues();
                }
            } else {
                m_FreeLook = null;
            }
        }

Is there a better way to switch VCams based on the active ViewType?

Thanks!
 
Instead of switching the VCams by switching the ViewTypes what do you think of adding an option to the ViewType that allows you to switch VCams?
 
In my use case i kinda want 2 seperate ViewTypes anyway.

Do you think of adding a property "VirtualCamera" of type CinemachineVirtualCameraBase to the Cinemachine ViewType and activate that "VirtualCamera" when the view becomes active? How would the VirtualCamera be set active? As far as I understand, it can either be done through priorities or by disabling/enabling VCam gameobjects ...

I am still figuring things out so maybe I can give a more qualified answer in a few days xD
 
You could still add a second view type, just specify a different virtual camera. It has been awhile since I last used Cinemachine so I'll get back to you on the best method.
 
Top