Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

LookAt center delay when camera activates

Discussion in 'Cinemachine' started by GijsSickenga, Jun 18, 2019.

  1. GijsSickenga

    GijsSickenga

    Joined:
    Apr 10, 2018
    Posts:
    5
    I'm creating a cinematic live montage of a racing game, akin to how a Formula 1 race is filmed.
    To this end I have placed a bunch of VirtualCameras in the scene that are tied to triggers on the racetrack.
    When the target vehicle passes such a trigger, the system cuts to an associated camera.
    To switch cameras I manually set the priority of the active camera to 100 and the rest to 0.

    For panning shots from the side of the road I use VirtualCameras with a Composer.
    Standby Update is set to "Never" since I have a lot of VirtualCameras in the scene, and the LookAt target may change during a camera cut.
    Below are the Composer settings for one of the cameras.

    upload_2019-6-18_17-16-11.png

    The issue I'm having is that when I switch cameras, the newly active camera aggressively reframes the shot to center the target, which is visible for 1 or 2 frames.
    This causes a rapid jerk that is very jarring when watching the live montage.

    I've tried disabling and re-enabling the VirtualCamera & GameObject, or setting all damping & deadzone values to 0, waiting a frame and then reverting them, to attempt to reframe the VirtualCamera before switching to it, but all attempts so far have failed to produce a result where the effect is mitigated.

    Any advice on how to make sure my camera is already looking at the target before switching to it, without having to turn on Standby Update on all VirtualCameras?
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,241
    aahh this is a very interesting problem. You want the vcams to be "warm" when you cut to them. Right now they're cold - meaning that the target will start centered and then move away because of damping. You want them pre-damped.

    The way to do this is to have them update in standby - i.e. when they're not active. The problem for you is that you have many vcams and don't want to pay for the performance, right?

    Then, you'll have to figure out a way to activate the vcam - at a lower priority - some frames before you cut to it, to let it warm up. Is there a way for you to know a few frames ahead of time which vcam you will activate? Maybe you can set your triggers to be a little early on the track, and your trigger function can activate the vcam (at a lower priority), then start a coroutine that waits a few frames before putting up the vcam's priority and simultaneously deactivating the outgoing vcam. Could that strategy work for you?

    Or here's another (simpler) idea. Make a custom blend curve that's completely zero everywhere. Use that for blending. Then, you can just activate the incoming vcam, and it will warm up for a few frames automatically (thanks to the blend curve) before taking effect suddenly when the "blend" is finished. The blend will look like a cut, but under the hood the incoming vcam will be warming up. Haven't tried it myself, but that might work. However, if you do it that way you won't get any camera cut events because CM will think it's blending, even though the effect looks like a cut.
     
  3. GijsSickenga

    GijsSickenga

    Joined:
    Apr 10, 2018
    Posts:
    5
    The issue I'm actually having is that my target doesn't even start centered when I cut to a camera, which is what is causing the nasty jerking from the framing it was at when it was last active, but having the damping prewarmed in addition to centering like you describe would be extra nice.

    And yes, the reason I'm not using the standby update is partly to save performance, and partly because the LookAt target of the camera system as a whole may switch when a cut happens, meaning the standby updating of a camera that changes targets right as it activates would have been worthless anyway.

    What you are suggesting is exactly what I have been trying, and failing, to achieve. I am looking for a way to activate a camera before switching to it, but am unaware of how to achieve that without making it the highest priority camera. How would you suggest I go about activating it at a lower priority?

    I may have a look at that blend curve idea idea in the meantime, that sounds like it might be a suitable fix. I'm not using the cut events currently as I am manually deciding when to switch cameras, so I know when a cut happens already.

    Thanks for the insightful tips and quick response!
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,241
    You might need the cut events if you're doing any temporal post-processing effects, like motion blur. Without the cut event, motion blur will think that the camera does a 1-frame swish instead of a cut, so the cut will be blurred out. Since you know when you're cutting, you'll have to manually reset any temporal effects you're using.

    Activate/deactivate the vcam with vcam.gameObject.SetActive(). When it's active, it will track its target provided that standby update is set to Always. Deactivated vcams will never be updated, regardless of their Standby Update settings.

    So, the strategy would be:
    1. Set all Standby Updates to Always
    2. Deactivate all the vcams with SetActive(false), except the current live one
    3. To pre-warm a vcam, activate it, and give it a lower priority. During this time 2 vcams will be active, but only the higher-priority one will drive the Camera
    4. To switch from warming to live, raise the priority of the incoming and deactivate the outgoing vcam
    If you're using the zero-blend idea, simply keep everything at the same priority, and have your trigger activate the incoming and deactivate the outgoing vcam at the same moment. The blend system will keep the deactivated outgoing vcam on artificial life-support until the blend is finished.
     
    Last edited: Jun 18, 2019
    GijsSickenga likes this.
  5. GijsSickenga

    GijsSickenga

    Joined:
    Apr 10, 2018
    Posts:
    5
    Thanks, I will try those and see what works best!
     
  6. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,241
    Great. Let me know how it goes :D
     
  7. GijsSickenga

    GijsSickenga

    Joined:
    Apr 10, 2018
    Posts:
    5
    I've tried the prewarming trick. It seems to work pretty well for transitioning the upcoming camera to the correct framing before switching to it, but a trick I was using is conflicting with it.

    The racetrack in the game goes vertical and upside down in places. In order to prevent gimbal lock on cameras that needed to point straight up, and to allow for sideways and upside down cameras, I allowed the designer to mark cameras with an "Override World Up" flag, which instantiates a GameObject at runtime with a desired Transform orientation determining the world up for that camera. When the system switches to such a camera, the Brain's World Up Override Transform is set to this value, in order to orient the incoming camera correctly.

    This is causing problems with the prewarming however. The world up switchover seems to be happening a frame late, visually, causing a reorientation of the camera's roll axis after it is switched to. I've tried doing the switch one or two frames early, but I seem to be having trouble getting it consistent. I want the switch to happen between cuts, so it's not noticable by the viewer.

    I realize it's a bit of an unorthodox method and if there's a better way to fix the gimbal lock issue, where for instance I could determine the world up for each camera separately, rather than having to set the Brain's Override World Up, that would be best. I'm not sure if that's possible though.

    Any tips on how to fix this issue?
     
  8. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,241
    Sure, you can write a custom extension to override the up vector per-vcam. Maybe something like this:
    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. /// <summary>
    5. /// An add-on module for Cinemachine Virtual Camera that overrides Up
    6. /// </summary>
    7. [SaveDuringPlay] [AddComponentMenu("")] // Hide in menu
    8. public class CustomCameraUp : CinemachineExtension
    9. {
    10.     [Tooltip("Use this object's local Up direction")]
    11.     public Transform m_Up = null;
    12.  
    13.     protected override void PostPipelineStageCallback(
    14.         CinemachineVirtualCameraBase vcam,
    15.         CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    16.     {
    17.         if (stage == CinemachineCore.Stage.Body && m_Up != null)
    18.             state.ReferenceUp = m_Up.up;
    19.     }
    20. }
    Drop it into your project, and it will automatically appear in the vcam's Extensions dropdown. This implementation uses a Transform to hold the up vector, but of course you can implement that any way you like.
     
    Last edited: Jun 19, 2019
    JoeJoe and GijsSickenga like this.
  9. GijsSickenga

    GijsSickenga

    Joined:
    Apr 10, 2018
    Posts:
    5
    Awesome, this is exactly what I was looking for! It works like a charm and is so much more elegant than my own duct tape solution. Thanks again for the helpful reply! :)
     
    Gregoryl likes this.
  10. KnightWhoSaysNi

    KnightWhoSaysNi

    Joined:
    Jan 21, 2017
    Posts:
    10
    @Gregoryl
    I have a spherical world and a bunch of objects on it, all around the world.
    I've added a CinemachineVirtualCamera to those objects and I'm using
    Body: FramingTransposer
    Aim: POV
    Follow and LookAt target is the same

    If the object (npc) is moving around the world I can rotate the camera around that npc correctly, without your extension. The camera game object as well as the target object are on the npc prefab (I'm guessing it would work even if they weren't on the prefab). The Body is following the npc, and Aim is allowing me to rotate.

    But if I add a virtual camera to an object that doesn't move, with the same settings: FramingTransposer and POV camera rotation seems to depend on the world up. Even with the CustomCameraUp extension there are no changes.

    I've also tested with this but still no change
    Code (CSharp):
    1.  if (stage == CinemachineCore.Stage.Aim && m_Up != null)
    2.             state.ReferenceUp = m_Up.up;
    [/ICODE]

    Overriding world up on the brain has no effect either for some reason.
    Axis Mouse X rotates around object's Z axis instead of object's Y axis.

    Any ideas of how to fix this?
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,241
    I'm having some doubts about your setup.

    Normally, the main camera (with the CM Brain), the vcam, and the tracked objects are all separate GameObjects, not in a parent/child relationship with each other (although they can all have a common ancestor). Is that the way you have it?

    One thing to know: the POV component on the vcam will use the vcam's parent's reference frame when rotating. So, that parent needs to be correctly oriented on your spherical surface.

    What version of CM are you using?
     
    KnightWhoSaysNi likes this.
  12. KnightWhoSaysNi

    KnightWhoSaysNi

    Joined:
    Jan 21, 2017
    Posts:
    10
    Thank you. The root of the prefab had a default orientation of -90, 0, 0, which then changes to something else entirely when instantiated on the world, but the initial -90 still messed up the camera.
    Now it works correctly.

    And we're using the latest CM. The brain is on a completely different game object. Other virtual cameras aren't in a pool of cameras, but are on the prefabs, with preset values, along with a target game object (where required).
     
    Gregoryl likes this.