Search Unity

Custom Cinemachine OnCameraBlendCompleteEvent implementation

Discussion in 'Cinemachine' started by Meatloaf4, Aug 11, 2019.

  1. Meatloaf4

    Meatloaf4

    Joined:
    Jul 30, 2013
    Posts:
    183
    Hey guys I've been messing around with Cinemachine code for the past few weeks and was a bit frustrated by the lack of a
    OnCameraBlendCompleteEvent
    in
    CinemachineBrain
    . So I did some work on the Cinemachine git repo to get it working (here for anyone curious). It became apparent later though that my implementation wasn't going to work in all cases and thus is not likely to get added to master.

    I took @Gregoryl advice though and whipped up my own CinemachineHelper script to fire an
    OnCameraBlendCompleteEvent
    as he suggested. Below is the result I've come up with. I figured I would share it in the hopes that it may help somebody :)

    Code (CSharp):
    1.  
    2. using Cinemachine;
    3. using UnityEngine;
    4.  
    5. namespace _Game_Assets.Scripts
    6. {
    7.     /// <summary>
    8.     /// Adds additional functionality and events to the <see cref="CinemachineBrain"/>
    9.     /// </summary>
    10.     public class CinemachineBrainHelper : MonoBehaviour
    11.     {
    12.         /// <summary>
    13.         /// THe cinemachine brain this class will help with
    14.         /// </summary>
    15.         [Tooltip("The cinemachine brain this class will help.")]
    16.         public CinemachineBrain cinemachineBrain;
    17.         /// <summary>
    18.         /// Invoked when the camera has completely blended from one camera to another. Signature = toCamera, fromCamera.
    19.         /// </summary>
    20.         [Space]
    21.         [Tooltip("Invoked when the camera has completely blended from one camera to another. Signature = toCamera, fromCamera.")]
    22.         public CinemachineBrain.VcamActivatedEvent onCameraBlendCompleteEvent;
    23.  
    24.         /// <summary>
    25.         /// In initial camera we were blending from. In other words the camera that started the blend sequence.
    26.         /// </summary>
    27.         private ICinemachineCamera fromCamera;
    28.         /// <summary>
    29.         /// The polling rate at which we will check if the IsBlending flag is set to false.
    30.         /// </summary>
    31.         private const float CHECK_BRAIN_IS_BLENDING_REPEAT_RATE = 0.1f;
    32.  
    33.         private void Awake()
    34.         {
    35.             cinemachineBrain.m_CameraActivatedEvent.AddListener(OnCameraActivatedEventHandler);
    36.         }
    37.  
    38.         /// <summary>
    39.         /// Attaches to <see cref="cinemachineBrain"/> in order to spawn our <see cref="onCameraBlendCompleteEvent"/>
    40.         /// when the cameras are finished blending (brain.IsBlending = false).
    41.         /// </summary>
    42.         /// <param name="toCamera">The camera we blended to.</param>
    43.         /// <param name="fromCamera">The camera we blended away from.</param>
    44.         private void OnCameraActivatedEventHandler(ICinemachineCamera toCamera, ICinemachineCamera fromCamera)
    45.         {
    46.             if (fromCamera == null)
    47.             {
    48.                 return;
    49.             }
    50.  
    51.             var oldFromCamera = this.fromCamera;
    52.             this.fromCamera = fromCamera;
    53.             if (oldFromCamera != null)
    54.             {
    55.                 return;
    56.             }
    57.             InvokeRepeating(nameof(CheckBrainIsBlending),0,CHECK_BRAIN_IS_BLENDING_REPEAT_RATE);
    58.         }
    59.  
    60.         /// <summary>
    61.         /// Invoked Repeatedly when our <see cref="cinemachineBrain"/> <see cref="m_CameraActivatedEvent"/> has fired
    62.         /// in order to poll <see cref="cinemachineBrain.IsBlending"/> to find when the blend has been completed.
    63.         /// </summary>
    64.         private void CheckBrainIsBlending()
    65.         {
    66.             if (!cinemachineBrain.IsBlending)
    67.             {
    68.                 CancelInvoke(nameof(CheckBrainIsBlending));
    69.                 onCameraBlendCompleteEvent?.Invoke(cinemachineBrain.ActiveVirtualCamera,fromCamera);
    70.                 fromCamera = null;
    71.             }
    72.         }
    73.     }
    74. }
    75.  
     
  2. Meatloaf4

    Meatloaf4

    Joined:
    Jul 30, 2013
    Posts:
    183
    qew_chang likes this.
  3. fixertkamura

    fixertkamura

    Joined:
    Aug 17, 2020
    Posts:
    4
    Thank you, it was helpful!
     
    Meatloaf4 likes this.
  4. Bmco

    Bmco

    Joined:
    Mar 11, 2020
    Posts:
    55
    If you don't need an anonymous event firing, I was able to achieve a similar effect with a co-routine.

    Code (CSharp):
    1.     void Update()
    2.     {
    3.         if(Input.GetKeyUp(KeyCode.Space))
    4.         {
    5.             if(rtsCamActive)
    6.             {
    7.                 vCamRTS.Priority = 0;
    8.                 vCamFPS.Priority = 1;
    9.                 StartCoroutine("FireOnEndBlend");
    10.             }
    11.             else
    12.             {
    13.                 vCamRTS.Priority = 1;
    14.                 vCamFPS.Priority = 0;
    15.                 StartCoroutine("FireOnEndBlend");
    16.             }
    17.  
    18.             rtsCamActive = !rtsCamActive;
    19.         }
    20.     }
    21.  
    22.     IEnumerator FireOnEndBlend()
    23.     {
    24.         while(brain.IsBlending == false) //It Takes a couple frames for the IsBlending to switch to true
    25.         {
    26.             Debug.Log("Not Yet");
    27.             yield return new WaitForEndOfFrame();
    28.         }
    29.  
    30.         while(brain.IsBlending)
    31.         {
    32.             Debug.Log("Blending");
    33.             yield return new WaitForSecondsRealtime(1);
    34.         }
    35.  
    36.         Debug.Log("Done!");
    37.     }
     
    Gregoryl likes this.