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. Dismiss Notice

Question Continue to update virtual cameras that are on standby

Discussion in 'Cinemachine' started by dillbacon55, Apr 10, 2021.

  1. dillbacon55

    dillbacon55

    Joined:
    Mar 24, 2014
    Posts:
    7
    What I'm trying to achieve

    I wanted to explain this just in case what I'm trying to do can already be achieved more easily.

    I want to pull the camera forward when it is occluded. When the camera gets too close to the player, I want to switch to a virtual camera that is at more of a top down view (but with almost identical settings, just different rig heights and radius), so the camera is not occluded. If the player is back in a position where the previously live virtual camera's camera position would be far enough away from the player, I want to switch back to the first virtual camera and continue like normal. Basically adding a little more power to the CinemachineCollider and not allowing the camera to get too close to the player.

    Note - I don't want to set "minimum distance from target" to solve the issue. When it gets too close, it gives up and clips through cliffs which isn't what I want (although I understand this is the expected behavior).

    My attempt so far

    I have 1 actual camera, and one object that is a "fake" camera (basically an empty game object with a camera brain). The camera and the fake camera have the same positions at all times, which is great.

    When I put the current virtual camera on standby and begin updating another virtual camera, the newly live virtual camera begins applying updates to the fake camera. I'd like the fake camera to continue receiving updates from the virtual camera that is on standby (I planned on applying the axis control values manually, as the virtual cameras are identical other than their height and radius).

    The problem is, the fake camera is taken over by the currently live virtual camera no matter what. I tried setting the fake camera's update method to "Manually Update", but then it simply doesn't update (obviously). Is there a way to simply continue to update the position without transitioning to the live virtual camera (possibly using ManualUpdate), even if it's on standby without transitioning to a different virtual camera? Maybe I'm completely overlooking something and there's a simpler way to achieve my desired results?

    Thank you!
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,234
    Try this:
    1. Have 2 vcams: the Normal one at the normal priority and a Top Down one at a lower priority.
    2. Add a custom script to the Normal vcam that checks distance from target. When the distance is too small, it lowers the vcam's priority so that the Top Down one becomes active. When the distance is large enough again, it raises the priority back up.
    That should do it. No messing around with standby update.
     
  3. dillbacon55

    dillbacon55

    Joined:
    Mar 24, 2014
    Posts:
    7
    Thanks for taking the time to answer this @Gregoryl

    Unfortunately, there is still the issue of knowing where the camera would be to send it back, since the new camera distance from the player would be where the second vcam was. So, checking the distance won't work in this situation. Forgive me for the messy explanation, it's a fairly common things games do but it's difficult to explain.

    I was able to come up with sort of a hacky solution by calling
    Code (CSharp):
    1. SetCameraOverride
    Not really ideal, but with a combination of this and updating the fake camera position all the time, It switches between the cameras well. There is a slight "hitch" when switching back to the regular camera. I'm guessing this is a result of me manually updating the fake camera position.

    It would be neat if the CinemachineColllider had an option to switch cameras when it got too close to the player, or even better, was approaching the player at a certain velocity. Then when it switched cameras, a checkbox to have it intelligently switch back to the first camera when it was going to be far enough away from the player again.
     
    Last edited: Apr 14, 2021
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,234
    You don't need a hack at all. Don't check the main camera's distance from the player, check the vcam's distance from the player using vcam.State.CorrectedPosition. That's where the vcam would place the main camera if this were the active vcam. You'll have to put your normal vcam's standby update mode to Always, to get the most up-to-date position.

    Just to be clear: this step
    involves this bit of code
    Code (CSharp):
    1. var distance = Vector3.Distance(normalVcam.State.CorrectedPosition, target.position);
     
  5. dillbacon55

    dillbacon55

    Joined:
    Mar 24, 2014
    Posts:
    7
    Cool, I was unaware of vcam.State.CorrectedPosition.

    Just tried it out. Works great, but it only takes into account position when you actually move the target, and not when you move the camera (It's a FreeLook camera - I probably should have mentioned that previously).

    Almost there though - maybe I'm overlooking something?
     
  6. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,234
    Sorry, I don't quite understand. You want to lower the freeLook's priority when the freeLook is too close to that target. freeLookState.CorrectedPosition will give you the freeLook's current position, including any freeLook movement. What exactly is the issue?

    EDIT - is it that freeLook only processes user input when live? If so, then you can manually pump the axis values while the vcam is not live, to keep it in sync with user movement
     
  7. dillbacon55

    dillbacon55

    Joined:
    Mar 24, 2014
    Posts:
    7
    For me, the x y and z positions only update when I move the target, not when I move the camera around the target.

    For example - I'm using the left joystick to move the player, and the right joystick to move the free camera around the player. When it enters the second vcam, I can see the values of the previous camera using CorrectedPosition when I move the player, but when I used the right joystick to move the camera the CorrectedPosition value doesn't change.

    Edit:

    If this isn't intended, it's possible I've done something with overriding controls on the new input system causing it to not get the additional position from moving around the target.

    Edit 2:

    Ah! Just saw your edit. I'll give that a shot.
     
  8. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,234
    Yes, that's because the freeLook doesn't process mouse movement unless the freeLook is actually live. You'll have to manually pump the input values into FreeLook.m_xAxis.InputValue and FreeLook.m_yAxis.InputValue from your script while the freeLook is in the lowered priority state. You can do that in your script's OnUpdate().
     
  9. dillbacon55

    dillbacon55

    Joined:
    Mar 24, 2014
    Posts:
    7
    That worked!

    Thank you again for your time Gregoryl.
     
    Gregoryl likes this.